【问题标题】:NHibernate inheritance create child object from parentNHibernate继承从父对象创建子对象
【发布时间】:2013-10-15 22:37:22
【问题描述】:

如果这是一个愚蠢的问题,我很抱歉,但我似乎无法掌握。

我有 2 个课程,CustomerMember

Customer.cs

public class Customer
{
    public virtual string Firstname { get; set; }
    public virtual string Middlename { get; set; }
    public virtual string Lastname { get; set; }
}

Member.cs

public class Member : Customer
{
    public virtual string MemberId { get; set; }
    public virtual string MemberRegistrationDate { get; set; }
    public virtual string MembershipStatus { get; set; }

    public Member()
    {
        MemberRegistrationDate = DateTime.Now;
        MembershipStatus = MembershipStatusEnum.Active;
    }
}

我很确定这必须是一个继承,其中 Member 是一个客户,但如果我很绝望,我可以求助于组合。

请注意,这里我使用的是 NHibernate,这会迫使我使用所有虚拟对象。

给定一个客户对象,现有客户的新成员应该如何?

我可以在这里想到 2 个选项:

1 - 使用 Member.cs 构造函数重新创建它的父属性

这是一件好事吗?我试着这样做:

public class Member : Customer
{
    public virtual string MemberId { get; set; }
    public virtual string MemberRegistrationDate { get; set; }
    public virtual string MembershipStatus { get; set; }

    public Member(Customer customer)
    {
       Firstname = customer.Firstname;
       Middlename = customer.Middlename;
       Lastname = customer.Lastname;

       MemberRegistrationDate = DateTime.Now;
       MembershipStatus = MembershipStatusEnum.Active;
    }
}

但是 Resharper 警告我关于在构造函数中访问虚拟成员,我同意避免这种情况,并告诉我将 Member 设为不能具有虚拟成员的密封类(不兼容 NHibernate)。

当有一天我向 Customer 类添加了一个新属性,而我忘记对 Member 构造函数做同样的事情时,这也引发了另一个问题。

2 - 使用某种反射助手在两个对象之间进行映射。

当然这是一个可行的选择,但我目前正在学习 DDD,我想知道是否可以将这样的助手放在域层中?

需要一些建议,谢谢!

【问题讨论】:

  • 你想做什么?我不太明白你的问题。 “注册”是什么意思? (这不是OOP中常用的术语...)
  • @ThomasWeller 很抱歉不清楚。最接近的含义是从现有的客户(父)对象创建一个新的成员(子)对象,并将所有现有父属性复制到子对象
  • @ThomasWeller 编辑了问题,感谢您的提醒 :)
  • 哦,这是否意味着:您有一个客户,并且您想从中创建一个新成员(“将客户转变为成员”),同时为附加属性提供一些默认值?跨度>

标签: c# oop nhibernate inheritance fluent-nhibernate


【解决方案1】:

不确定我是否正确,但没有必要在您的 Member 课程中做任何与 Customer 相关的事情。您只需要告诉 NHibernate Member 从 Customer 派生,并且您需要为这两个类提供正确的映射。就是这样,其余的会自动进行(无论如何,这就是 OOP 中继承的全部意义)。

关于您的第二个问题(“不要在 c'tor 中调用 virtuals。”):这在理论上是正确的,但只有当派生类中的虚拟方法有可能被覆盖时才有意义。因此,您可以放心地忽略此处的 R# 警告。

但我认为完全摆脱 Member c'tor 并像这样声明类是最干净的:

public class Member : Customer
{
    private memberRegistrationDate = DateTime.Now;
    private membershipStatus = MembershipStatusEnum.Active;

    public virtual string MemberId { get; set; }
    public virtual string MemberRegistrationDate 
    { 
      get { return this.memberRegistrationDate; }; 
      set { this.memberRegistrationDate = value; }; 
    }
    public virtual string MembershipStatus 
    { 
      get { return this.membershipStatus; }; 
      set { this.membershipStatus = value; }; 
    }
}

编辑: 如果您正在寻找一种将客户转变为会员的简单方法,您可能应该完全将转换代码远离您的类,并将其放入扩展方法中(以保持清洁):

public static class CustomerExtensions
{
    public static Member ToMember(this Customer customer)
    {
        var member = new Member();
        member.Firstname = customer.Firstname;
        member.Middlename = customer.Middlename;
        member.Lastname = customer.Lastname;

        return member;
    }
}

你可以这样称呼它:

Member member = customer.ToMember();

【讨论】:

  • 嗯.. 不知道我明白了.. 你能给我举个例子如何将客户“投射”给会员吗?
  • 编辑了答案。是不是更接近你要找的东西?
  • 嗯.. 不是真的,这很像我的第一个选项,当我想向客户添加新属性时,这是一个问题。这只是我能想到的一个想法..
  • 基本上,你是对的。但是如果你想实现“自动添加新属性”的事情,这只有通过复杂且非常慢的反射代码才能实现。我怀疑这是否值得。
  • 我确实想尽可能地避免使用反射。我会等待另一种意见,但如果没有或有类似的意见,我会接受你的回答: )
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-14
  • 1970-01-01
  • 1970-01-01
  • 2013-10-15
  • 2010-10-12
  • 2015-02-01
  • 1970-01-01
相关资源
最近更新 更多