有没有办法将基类转换为派生类?
以下是两个类的简单示例:
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编写另一个构造函数或设置每个属性的方法之外,还有其他解决方案吗?
答案 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 Pattern向Contact
类添加特殊功能,为其提供SpecialContact
的功能而无需子类化。