重载构造函数和重用代码

dno*_*ord 4 c# oop constructor

比方说,我有一个对象Customer有几个属性(ID,FirstName,LastName).我有默认的构造函数Customer(),但后来我也有了Customer(DataRow dr),因为我从数据库加载这个对象,这是一个简单的方法.

我经常谈到我想要设置另一个构造函数的地方,Customer(int ID)有时我想要加载一个Customer但是我还没有去过数据库.对我来说最简单的方式似乎是这样的:

Customer(int ID)
{
    DataTable dt = DataAccess.GetCustomer(ID);
    if (dt.Rows.Count > 0)
    {
        // pass control to the DataRow constructor at this point?
    }
    else
    {
        // pass control to the default constructor at this point?
    }   
}
Run Code Online (Sandbox Code Playgroud)

重用已经在DataRow构造函数中的代码是有意义的,但我无法找到一种方法来调用它并返回它给我的内容.通过谷歌搜索,我发现了有关使用: this()语法重构的构造函数的信息,但所有这些示例似乎都是向后或与我正在尝试的内容不兼容.

所以我对构造函数的理解存在差距,但我似乎无法解决它.我错过了什么?

Pol*_*ker 10

最简单的解决方案似乎是:构造另一个函数来完成你想要做的工作并让两个构造函数都调用该函数.


Jon*_*jap 6

我担心你没有得到的不是关于构造函数,而是关于单一责任原则和松散耦合.

例如,您在上面显示的代码表示:

  • 您的域模型包含数据访问代码
  • 您不会重用基类中的任何代码,这些代码可能首先注入了数据访问逻辑
  • 您的域对象知道除其自身或其成员之外的数据结构,如DataTable或DataRow,它将这些数据结构与这些数据结构联系起来,并且使得使用其他数据结构变得很麻烦.

当然,这假设您没有使用ActiveRecord模型,这似乎是这里的情况,但仍然会通过紧耦合实现.

我的偏好是域对象只包含与保存和操作真正的客户数据相关的逻辑,没有别的.因此,我的构造函数将是:

class Customer
{
    public Customer(int id, string firstName, string LastName)
    {
        Id = id;
        FirstName = firstName;
        LastName = lastName;
    }

    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

更新:话虽这么说,这是为什么有些人更喜欢允许POCO的ORM的主要原因,比如NHibernate:没有必要在那里放置数据加载逻辑.

例如,如果这是在NHibernate中完成的,那么你需要一个DomainObject基类:

public class Customer : DomainObject
Run Code Online (Sandbox Code Playgroud)

而NHibernate的IRepository实现又可以使用它:

public class Repository<T> : IRepository where T : DomainObject
Run Code Online (Sandbox Code Playgroud)

Repository对象将包含CRUD操作所需的所有代码.

如果您希望坚持使用ADO.NET,一种可能的解决方案是为所有加载创建DAL管理器对象:

public class CustomerManager
{
    public IList<Customer> LoadCustomers()
    {
        //load all customers here
        foreach (DataRow dr in dt.Table[0])
        {
             yield return new Customer((int) dr["Id"], dr["FirstName"].ToString(), dr["LastName"].ToString());
        }
    }

    public Customer LoadCustomerByID(int id)
    {
        //load one customer here
        return new Customer((int) dr["Id"], dr["FirstName"].ToString(), dr["LastName"].ToString());
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,这里还有很多机会进一步促进代码重用.