将类转换为派生类

时间:2012-02-12 22:23:57

标签: c# inheritance

有没有办法将基类转换为派生类?

以下是两个类的简单示例:

namespace BLL
{
    public class Contact 
    {
       public int ContactID { get; set; }
       public string Name { get; set; }

       public Contact(){}
    }
}

namespace BLL
{
    public class SpecialContact : Contact
    {
       public SpecialContact(){}
    }
}

理想情况下,我可以这样做:

Contact contact = new Contact();
SpecialContact specialContact = new SpecialContact();

contact.ContactID = 123;
contact.Name = "Jeff";

specialContact = contact;

此代码当然会抛出错误。除了为SpecialContact编写另一个构造函数或设置每个属性的方法之外,还有其他解决方案吗?

5 个答案:

答案 0 :(得分:3)

Base类引用分配给Derived类引用变量是非法的。

X类型的变量只能是对X类型或派生类型的对象的引用。

您可能需要另一个SpecialContact实例,其中包含与现有对象相同的数据。无法避免手动复制。

当我需要将匹配属性从一个对象复制到另一个不兼容的对象(1)时,我使用以下扩展方法:

public static void AssignFrom(this object destination, object source) {
  Type dest_type = destination.GetType();
  Type source_type = source.GetType();

  var matching_props = from d in dest_type.GetProperties()
                        join s in source_type.GetProperties()
                        on d.Name equals s.Name
                        where d.IsWritable() && s.IsReadable()
                        select new {
                          source = s,
                          destination = d
                        };

  foreach (var prop in matching_props) {
    prop.destination.SetValue(destination, prop.source.GetValue(source, null), null);
  }
}

然后你可以这样做:

specialContact.assignFrom(contact);

请考虑这是一种解决方法。正确的解决方案是正确设计您的类层次结构,而不会遇到此问题。


1注意:它按名称匹配属性,并假设它们属于同一类型。

答案 1 :(得分:3)

如果您只是对 将属性 从一个类实例复制到另一个类感兴趣(无论这些类的关系如何),您可以使用像{{3这样的映射工具}}

您的具体示例如下所示:

Mapper.CreateMap<Contact, SpecialContact>();
Contact contact = new Contact();
contact.ContactID = 123;
contact.Name = "Jeff";
SpecialContact specialContact = Mapper.Map<Contact, SpecialContact>(contact);

答案 2 :(得分:2)

  

除了为SpecialContact编写另一个构造函数或设置每个属性的方法之外,还有另一个解决方案吗?

不,不是真的。
您可以使用Reflection自动化它,但这就是它。

但是请注意,通过适当的设计,这几乎不应该被要求。它不是(派生)类的正常使用。

如果合同随着时间的推移可以转换为SpecialContracts,那么您要么创建一个新对象,要么使用ContactType属性对其进行建模,也可以使用一些合成。

答案 3 :(得分:1)

  

此代码当然会抛出错误。在写另一个之外   SpecialContact的构造函数或设置每个属性的方法是   有另一种解决方案吗?

不,没有其他办法。如果您想避免进行所有手动复制,反射可能会对您有所帮助。

答案 4 :(得分:1)

除了重新考虑你的继承层次结构迫使你做这种有点不正统的操作外,你有几个解决方案,都需要一些编码。

  • 您可以向基类添加显式转换运算符
  • 您可以添加一个为您复制的扩展方法

就转换继承层次结构而言,您可以使用Decorator Design PatternContact类添加特殊功能,为其提供SpecialContact的功能而无需子类化。