0

这个问题与我之前提出的问题非常接近,但我认为它们不是同一件事,所以认为将它们分开是明智的(当你听到这个问题时,这有点讽刺)。

上一个问题

我有一个分为两个项目的 Web 应用程序:

1) ASP.NET 站点 2) 包含业务对象、逻辑层方法和 DAL 方法的 DLL。它们分为不同的名称空间,但都在同一个 DLL 中。

我越看它并扩展开发,我就越意识到我走错了路。我想将它们拆分为单独的 DLL,以便我可以明确划分职责。

一旦我在不同的 DLL 中有代码,我意识到很多类相互调用。例如,当在 DAL 中创建客户对象列表时,它还会调用 companyDAL.cs 并获取客户所属的公司列表。所以我现在有两个直接相互引用的类。这似乎是一件相当糟糕的事情!它闻起来很糟糕,但我继续前进,并试图在我能做到的地方把事情分开。

为此,我将所有对象取出到接口,并将对它们的所有引用更改为接口。

我希望使用某种 DI(目前只是了解这一点),因此对于每个对象,我创建了一个构造函数,该构造函数为该 DLL 接收一个工厂,(该工厂将为该类可能的每个对象创建一个新实例要求)。我还放置了一个默认构造函数,它将使用默认工厂调用 DI 构造函数,以确保始终使用一个工厂。

一切都编译好了,所以我试了一下,得到了一个stackoverflow!这是我完全意识到,如果我有两个相互需要的类,那么没有另一个就无法实例化。

Factory
{
   IClient CreateNewIClient()
   {
         return new Client();
   }

   ICompany CreateNeIwCompany()
   {
          return new Company();
   }
}

Client
{
    private ICompany _company;

    public Client() : this (new Factory()) {}

    public Client(Factory factory)
    {
        _company = factory.CreateNewICompany();
    }

    public Client GetClientbyID(int id)
    {
       .... do stuff to get client from db
       ... got client object and companyid from db.
         client.Company = _company.GetCompanybyID(companyid);
        return client;
    }
}

 Company
 {
    private IClient _client;

    public Company() : this (new Factory()) {}

    public Company(Factory factory)
    {
        _client = factory.CreateNewIClient();
     }

    public Company GetCompanyWithAllClients(int companyid)
    {
         .... do stuff to get a company out and client ids
         .... for each client id found
          company.Clients.add(_client.GetClientByID(clientid));
          return company;
    } 
 } 
  • 我是不是把 DI 的事情都搞错了,工厂的想法好吗?

  • 我应该如何避免彼此需要的课程?他们现在这样的原因是为了避免重复代码。我确信我可以编写更简洁的 SQL 以一次性完成,或者至少在同一方法中的几个查询中,但我试图避免在不同的地方重复代码。

感谢您的任何建议。

4

2 回答 2

1

这与其说是对问题的澄清,不如说是一个答案。我认为您的工厂使事情变得有些复杂(因为您得到堆栈溢出异常而不是根本无法编译)。

问题是循环依赖。没有 B 的实例就不能实例化 A,没有 A 的实例就不能实例化 B 的实例。

public class Company : ICompany
{
    private IClient _client;

    // OK so first build a client and pass it in
    public Company(IClient client)
    {
       _client = _client;
    }
}

public class Client : IClient
{
    private ICompany _company;

    // OK so first build a company and pass it in.  Oh.  I can't... :(
    public Client(ICompany company)
    {
        _company = company;
    }    
}

Misko 有一篇关于此的文章可能会有一些用处: http: //misko.hevery.com/2008/08/01/circular-dependency-in-constructors-and-dependency-injection/

基本上:您的课程设计是问题所在,需要修复。工厂只是混淆了这个问题:)

于 2009-04-18T17:10:04.533 回答
0

Maybe you could use some ORM tool for you DAL, like NHibernate or Linq to SQL? NHibernate will map your data into objects with bi-directional links (if you want).

Edit: typo

Cheers, Rok

于 2009-04-18T16:17:08.917 回答