C#多态性问题

时间:2009-11-06 22:17:52

标签: c# architecture

我有一个名为的A类,一个名为DTO的DTO类。现在假设我想在我的DTO中添加更多属性。所以我从现有的DTO中派生出一个新的DTO类,并为它添加属性。下面是代码:

namespace TestConsole
{
    class test
    {
        static void Main(string[] args)
        {

            B b = new B();
            b.D.ID = 1;
            b.D.Name = "4";
            MyBLMethod(b);

        }
        static void MyBLMethod(A b)
        {
            MyDALMethod(b.D);
        }

        static void MyDALMethod(DTO dto)
        {
           int i = dto.ID;
           string name = ((MyDTO)dto).Name;//I could not do this 
            //because i will get object cast error as i can't cast from 
            //parent to child
        }

    }
    public class DTO
    {
        public int ID = 99;
        public DTO()
        {
        }

        public DTO(DTO source)
        {
            ID = source.ID;
        }
    }

    public class MyDTO : DTO
    {
        public string Name = "";
        public MyDTO() { }
        public MyDTO(MyDTO source)
            : base(source)
        {
            Name = source.Name;

        }
    }
    public class A
    {
        private DTO _d;
        public A()
        {
            D = new DTO();

        }

        public DTO D
        {
            get { return _d; }
            set { _d = value; }
        }
    }

    public class B : A
    {
        private MyDTO _md;
        public B()
        {
            _md = new MyDTO();

        }

        public MyDTO D
        {
            get { return _md; }
            set { _md = value; }
        }
    }

}

从Main(您可以将其视为UI)我调用MyBLMethod(存在于BL存储库中)并将类对象传递给它,并且从BL存储库调用我的DAL。在DAL中我写了这个:

static void MyDALMethod(DTO dto)
{
    int i = dto.ID;
    string name = ((MyDTO)dto).Name;//I could not do this 
       //because i will get object cast error as i can't cast from 
       //parent to child
}

您能否建议我如何在DAL中获取新扩展的属性(示例中的名称)。

5 个答案:

答案 0 :(得分:4)

当B继承A时,它已经拥有DTO属性。所以问题实际上是你隐藏了这个继承。你不需要B类中的新属性,只需在类构造函数中设置它。

public class B : A
    {
        public B()
        {
            this.D = new MyDTO();
        }

    }

但是,在您的主要课程中,您需要在您的属性中进行显式转换,就像下面一样,因为DTO没有“名称”属性。

static void Main(string[] args)
        {
            B b = new B();
            b.D.ID = 1;
            ((MyDTO)b.D).Name = "4";
            MyBLMethod(b);
        }

答案 1 :(得分:3)

如果对象实际上是基本类型,则不能仅仅添加其他属性。这样做不对,抱歉。

你想要的是转换对象(也许)。在您的子类中创建一个构造函数,该构造函数可以将父项复制到其自身 - 然后您将拥有其他属性。

答案 2 :(得分:3)

转换失败的原因是您没有将MyDTO对象传递给方法,而是传递DTO对象。即使存在MyDTO对象,MyBLMethod方法也始终将DTO对象发送到DAL。

您尚未将D属性设为虚拟。这意味着当您在A引用上使用D属性时,即使实际对象发生在B实例上,也可以获得A类包含的DTO对象,以便它也具有MyDTO对象。

您可以使D属性虚拟化以访问实际对象的D属性,而不是由引用类型指定的属性。

或者您可以将引用转换为B,以便您可以访问它的MyDTO对象而不是它的DTO对象:

static void MyBLMethod(A b) {
   MyDALMethod(((B)b).D);
}

请注意,B类包含DTO和MyDTO对象,这可能不是您真正想要的。

答案 3 :(得分:2)

听起来你正在失去“分辨率”,因为你正在通过静态业务逻辑方法。我建议重新审视那部分而不是先用DAL方法挣扎。

可能有一个原因让你坚持下去,所以如果你这样做,你可以考虑使用反射来找到你需要的属性,或者使用“as”强制转换,然后在你的dal方法中测试null。如果你没有坚持这个设计,我会重构出静态方法。静态似乎很容易,不幸的是有很多代码'质量'工具会让你把方法设为静态,忘记提醒你以后不能轻易地将静态方法改为虚方法。

答案 4 :(得分:1)

允许BA的构造函数中传递DTO A个对象。如果需要,请创建构造函数protected。然后,B.D施放A.D

public class A
{
    private DTO _d;

    // New constructor.
    protected A(DTO d)
    {
        _d = d;
    }

    // Old constructor calls new constructor.
    public A() : this(new DTO())
    {
    }

    public DTO D
    {
        get { return _d; }
        set { _d = value; }
    }
}

public class B : A
{
    // Old B constructor calls new A constructor.
    public B() : base(new MyDTO())
    {
    }

    new public MyDTO D
    {
        // Getting D casts A.D instead of using an object exclusive to B.
        get { return (MyDTO)base.D; }
        set { base.D = value; }
    }
}