采用N层架构的类设计

时间:2009-04-18 16:06:50

标签: class-design

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

Previous question

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

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

我越是看着它并扩展了发展,我就意识到自己走错了路。我想把它们拆分成单独的DLL,以便我可以清楚地分离职责。

一旦我将代码放在不同的DLL中,我意识到很多类都相互调用。例如,当在DAL中创建客户端列表对象时,它还将调用companyDAL.cs并获取客户端所属的公司列表。所以我现在有两个直接相互引用的类。这似乎是一件相当糟糕的事情!它闻起来很糟糕,但我坚持下去,并尽力将事情分开。

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

我希望使用某种DI(目前只是了解它)所以对于每个对象,我创建了一个构造函数,为该DLL接受了一个Factory,(这个工厂将创建每个对象的新实例)班级可能要求)。我还设置了一个默认构造函数,它将使用默认的Factory调用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来一次性完成所有工作,或者至少在同一方法中的几个查询中,但我试图避免在不同的地方重复代码。

感谢您提出的所有建议。

2 个答案:

答案 0 :(得分: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/

基本上:你的班级设计是问题,需要修复。工厂只是混淆了这个问题:)

答案 1 :(得分:0)

也许你可以为你使用一些ORM工具DAL,比如NHibernate或Linq to SQL? NHibernate会将您的数据映射到具有双向链接的对象(如果需要)。

编辑:拼写错误

干杯, 韩国