C#类的奇怪继承问题

时间:2010-07-08 00:21:48

标签: c# .net inheritance properties

public class DTOa
{
    public int Id { get; set;}
    public string FirstName { get; set;}
}

public class DTOb: DTOa
{
    public string Email { get; set;}
    public string Password { get; set; }
}

public class a
{
    protected DTOa _DTO = new DTOa();
    public int Id
    {
        get
        {
            return _DTO.Id;
        }
        set
        {
            _DTO.Id = value;
        }
    }

    public string FirstName
    {
        get
        {
            return _DTO.FirstName;
        }
        set
        {
            _DTO.FirstName = value;
        }
    }

    public DTOa ToValueObject()
    {
        return _DTO;
    }
}

public class b: a
{
    protected DTOb _DTO = new DTOb();

    public string Email
    {
        get
        {
            return _DTO.Email;
        }

        set
        {
            _DTO.Email = value;
        }
    }

     public string Password
    {
        get
        {
            return _DTO.Password;
        }

        set
        {
            _DTO.Password  = value;
        }
    }

    public DTOb ToValueObject()
    {
        return _DTO;
    }
}

现在让我们执行以下代码

public function test() 
{       
   var a = new a();
   var b = new b();
   b.Id = 100;
   b.FirstName = "Jim";
   b.Email = "email@email.com";
   b.Password = "test";
   Console.WriteLine(b.ToValueObject().Dump());
}

问题在于

  1. 我希望b.ToValueObject设置了所有属性,但实际上只从DTOb类获取属性(所以我的FirstName和Id属性为NULL,但我明确设置了)

    dump:
    {
            Email: email@email.com,
            Password: test,
            Id: 0
    }
    
  2. 为什么没有设置ID并且没有设置FirstName的任何想法? DTOb继承自DTOa,因此“应该”包含来自DTOa的所有属性。它正在代码级别上工作,所以如果我写的话 console.WriteLine(b.Firstname) - 我会得到正确的值,但是当我调用ToValueObject()方法时 - 它已被删除。


    好的,这是一个有效的例子:

    public class DTOa : IDTO
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
    }
    
    public class DTOb : DTOa, IDTO
    {
    
        public string Email { get; set; }
        public string Password { get; set; }
    }
    
    public class a
    {
        protected IDTO _DTO;
    
        public a()
        {
            _DTO = new DTOa();
        }
    
        public int Id
        {
            get
            {
                return (_DTO as DTOa).Id;
            }
            set
            {
                (_DTO as DTOa).Id = value;
            }
        }
    
        public string FirstName
        {
            get
            {
                return (_DTO as DTOa).FirstName;
            }
            set
            {
                (_DTO as DTOa).FirstName = value;
            }
        }
    
        public DTOa ToValueObject()
        {
            return (_DTO as DTOa);
        }
    
    }
    
    public class b : a
    {
        public b()
        {
            _DTO = new DTOb();
        }
    
        public string Email
        {
            get
            {
                return (_DTO as DTOb).Email;
            }
    
            set
            {
                (_DTO as DTOb).Email = value;
            }
        }
    
        public string Password
        {
            get
            {
                return (_DTO as DTOb).Password;
            }
    
            set
            {
                (_DTO as DTOb).Password = value;
            }
        }
    
        public DTOb ToValueObject()
        {
            return _DTO as DTOb;
        }
    }
    

4 个答案:

答案 0 :(得分:6)

  

DTOb继承自DTOa,因此“应该”包含DTOa的所有属性

这是事实,但你也有:

public class a
{
    protected DTOa _DTO = new DTOa();
    ...
}

public class b
{
    protected DTOb _DTO = new DTOb();
    ...
}

即,类ab都在使用“DTO”类的不同实例。实际上,您的编译器应该在_DTO隐藏“b中的_DTO字段时向您发出警告{<1}}。

您要做的是确保两个类都访问同一个实例。你不能覆盖字段,但你可以覆盖方法,所以这样的东西可能是合适的:

a

老实说,我不太确定这个“DTO”对象的好处是什么,但上面应该会给你你所追求的行为。

答案 1 :(得分:0)

这是因为您的b类创建了自己的DTO对象(protected DTOb _DTO = new DTOb())并对其进行了修改,而您的a类创建了自己的DTO对象( protected DTOa _DTO = new DTOa())并修改此内容。

您的b课程在任何阶段都不会将其对象传递给a进行修改。

此外,您的GetValueObject只会返回该类中的实例。

要获得您想要的东西,您需要一个属性:

public DTOa DTO { get; }

b课程中重写了哪一项,并确保通过此调用设置了所有设置的方法。当你使用它时,你必须使用b进行一些投射。

答案 2 :(得分:0)

您应该收到有关_DTO字段和ToValueObject方法的警告,该方法隐藏了类a中的相应字段/方法。发生的事情是,类b对象同时具有DTOa和DTOb对象(均称为_DTO)和方法中的方法引用DTOa对象,b中的方法引用DTOb对象。

就我个人而言,我认为你的方式是错误的。看起来您正在尝试使用联系信息为用户和用户建模。我建议这里没有真正的继承关系(“是一个”),而是“有一个”关系 - 用户有联系信息。如果你以这种方式建模你有UserDTO和ContactDTO,你的用户对象将同时包含UserDTO和ContactDTO(或者对具有ContactDTO对象的Contact的引用)。

答案 3 :(得分:0)

我认为用你的a和b类复制DTOa和DTOb的功能没什么意义。它通常是一种反模式,除非你有特定的理由在数值到达DTOa之前拦截它们。

无论如何,您可以使用一些泛型来修复代码。

public class a<T> where T : DTOa {
    private readonly T _DTO = Activator.CreateInstance<T>();

    protected T DTO { get { return this._DTO; } }

    //properties
}

public class b<T> : a<T> where T : DTOb {
    //NB: Don't override or hide DTO.
    //properties
}


var a = new a<DTOa>();
var b = new b<DTOb>();
b.Id = 100;
b.FirstName = "Jim";
b.Email = "email@email.com";
b.Password = "test";