【问题标题】:C# polymorphism issueC#多态问题
【发布时间】:2009-11-06 22:17:52
【问题描述】:

我有一个名为:A 的 BL 类,名为: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 中获取新扩展的属性(示例中的名称)。

【问题讨论】:

  • 你确定转换会抛出异常吗?
  • 是的,上面的转换将抛出“无法将'TestConsole.DTO'类型的对象转换为'TestConsole.MyDTO'”异常。

标签: c# architecture


【解决方案1】:

当 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);
        }

【讨论】:

    【解决方案2】:

    如果对象实际上是基本类型,则不能只添加附加属性。那样不行,抱歉。

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

    【讨论】:

    • 我认为你没有抓住重点......他向 BL 发送了一个包含 MyDTO 对象的对象,但未能将其发送到 DAL。
    • 嗯 D() 不能是虚拟的,因为返回类型与写入的不同,所以可能有一些有效的方法来修复它。
    • @Jason:确实如此,但不同的返回类型并没有用于任何事情,因此可以将其更改为相同的,以便属性可以是虚拟的。
    【解决方案3】:

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

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

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

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

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

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

    【讨论】:

      【解决方案4】:

      听起来您正在失去“解决方案”,因为您正在通过静态业务逻辑方法。我建议重新审视那部分,而不是首先使用 DAL 方法。

      这可能是您坚持这一点的原因,因此,如果您是这样,您可以考虑使用反射来查找您需要的属性或使用“as”强制转换,然后在您的 dal 方法中测试 null。如果您不坚持这种设计,我会重构我的静态方法。静态方法看起来很简单,不幸的是,有很多代码“质量”工具迫使您将方法设为静态方法,但忘记提醒您以后不能轻易将静态方法更改为虚拟方法。

      【讨论】:

        【解决方案5】:

        允许BA 的构造函数中传递A 一个DTO 对象。如果需要,使构造函数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; }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-27
          • 1970-01-01
          • 1970-01-01
          • 2010-12-26
          • 2015-10-07
          相关资源
          最近更新 更多