Tel*_*ian 20 .net c# type-conversion
Class A { }
Class B : A { }
B ItemB = new B();
A ItemA = (A)B;
Console.WriteLine(ItemA.GetType().FullName);
Run Code Online (Sandbox Code Playgroud)
是否可以执行类似上面的操作并让编译器打印出类型A而不是类型B.基本上,是否可以永久地转换对象以使其"丢失"所有派生数据?
小智 11
我最近遇到了将旧项目迁移到Entity Framework的问题.如上所述,如果您有来自实体的派生类型,则无法存储它,只能存储基类型.解决方案是带反射的扩展方法.
public static T ForceType<T>(this object o)
{
T res;
res = Activator.CreateInstance<T>();
Type x = o.GetType();
Type y = res.GetType();
foreach (var destinationProp in y.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
{
var sourceProp = x.GetProperty(destinationProp.Name);
if (sourceProp != null)
{
destinationProp.SetValue(res, sourceProp.GetValue(o));
}
}
return res;
}
Run Code Online (Sandbox Code Playgroud)
它不是太整洁,所以如果你真的没有其他选择,请使用它.
Ani*_*Ani 10
您要求的是不可能的,原因有两个:
ItemA.GetType()不返回变量的编译时类型ItemA-它返回运行时类型的对象称为通过ItemA.(A)B在表示改变转换(即新A对象)中产生结果,因为用户定义的转换运算符(这里你唯一的希望)不能从派生转换为基类.您将获得正常,安全的参考转换.除此之外,你要求的是非常奇怪的; 人们会认为你真的很难违反Liskov的替代原则.这里肯定存在严重的设计缺陷,你应该解决.
如果你还想这样做; 你可以写手动构建一个方法A,从一个B由newing了一个A过来,然后复制数据.这可能作为ToA()
实例方法存在B.
如果您将此问题描述为"如何从现有A构造A?",则更有意义:创建一个复制构造函数A,其声明类似public A(A a){...},与子类特定的详细信息无关.这为您提供了A从现有实例A或其子类之一创建的一般方法.
为了娱乐,如果你想丢失所有派生数据,你可以这样做:
class Program
{
[DataContract(Name = "A", Namespace = "http://www.ademo.com")]
public class A { }
[DataContract(Name = "A", Namespace = "http://www.ademo.com")]
public class B : A {
[DataMember()]
public string FirstName;
}
static void Main(string[] args)
{
B itemB = new B();
itemB.FirstName = "Fred";
A itemA = (A)itemB;
Console.WriteLine(itemA.GetType().FullName);
A wipedA = WipeAllTracesOfB(itemB);
Console.WriteLine(wipedA.GetType().FullName);
}
public static A WipeAllTracesOfB(A a)
{
DataContractSerializer serializer = new DataContractSerializer(typeof(A));
using (MemoryStream ms = new MemoryStream())
{
serializer.WriteObject(ms, a);
ms.Position = 0;
A wiped = (A)serializer.ReadObject(ms);
return wiped;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您使用调试器,您将看到FirstName在转换为A时仍存储在FirstName字段中,当您从WipeAllTracesOfB获得A时,没有FirstName或任何B的跟踪.