将子对象强制转换为父类型以进行序列化
本文关键字:类型 序列化 父类 对象 转换 | 更新日期: 2023-09-27 18:22:12
我需要能够将子对象的实例强制转换为其父对象的实例。
public class Parent
{
public string name{ get; set; }
}
public class Child : Parent { }
var myClass = new Child();
(Parent)myClass;
上面的强制转换似乎不起作用,并且在序列化时,对象仍然具有子对象的类型。
还有别的办法吗?
我只使用子类进行验证——出于序列化的原因,我需要子类只具有父类的类型。
您没有将强制转换分配给任何内容。
var myClass = new Child();
Parent p = (Parent)myClass;
编辑-我想你误解了选角的工作原理。假设Parent有一个virtual
方法DoStuff()
,该方法在Child
中被重写。即使将myClass
强制转换为Parent
,它也将运行Child
的DoStuff
方法。不管怎样,Child
就是Child
,而且永远都是Child
,即使你投了它
如果你试图将它传递给一个接受Parent
对象的方法,你不必强制转换它。它已经是Parent
了,因为它是Child
。
我想我们错过了什么。你想搭讪什么?什么不起作用?
应该可以。
但我怀疑,从您编写代码的方式来看,您没有在新变量中捕获强制转换对象?试试这个:
var myClass = new Child()
var myClassAsParent = (Parent)myClass;
// myClassAsParent still has the type "Child", but can be accessed as if it were a Parent.
编辑根据您留下的一些评论,我相信您误解了大多数编程语言的一个基本方面。它是这样的:对象的类型不能更改。实例化为Child
对象的对象将始终是Child
对象。
投射不会更改对象的类型。铸造改变了程序其余部分"看到"对象的方式。如果您愿意的话,它会更改对象的界面。因此,如果将Child
对象强制转换为Parent
类型,程序的其余部分会认为它处理的是Parent
类型,但实际上是处理的是一个Child
类型,用一个非常糟糕的比喻来说,就是披着父对象的衣服。
简言之,铸造并没有做到你认为的那样。
问题是xml序列化程序将具有子类型的对象序列化为根元素。我真的不想一直通过我的目标类型向下进入串行器。有更好的方法吗Jules
我没有太多地使用序列化,但我的猜测是,您将需要更改"的定义;我如何序列化自己";在子元素中,将自己写成父元素。
如果你想实际拥有一个"的实例;父";然后你需要创建一个新的父级,并将所有值从子级复制到该父级(如果你有很多,我不会这么做,但如果你没有那么多,那应该不会有问题)。
最简单的方法是在Parent中创建一个复制构造函数。它将是一个构造函数,它将Parent作为参数,并将参数中的值(在本例中为Name,我认为您可能忽略了其他值)复制到参数本身。
然后,您可以创建一个新的Parent,将Child作为参数传入(由于Child是Parent,因此不需要强制转换/转换),它将吐出Parent的实际实例。
我在这里迟到了大约五年,但是。。。
您可以使用AutoMapper来解决您的问题。
只需定义父类和子类之间的映射即可。最简单的映射就可以了。在定义映射的类中:
CreateMap<Child, Parent>();
然后,在代码中的任何一点,您都可以执行以下操作:
Child child = new Child();
Parent parent = Mapper.Map<Parent>(child);
并且您的parent
对象将是一个纯Parent
,不具有任何child
对象属性。
正如其他人所说,铸造一个对象将保留其类型。这只会改变指针。但AutoMapper会创建目标类型的新实例,并将参数中的值复制到目标类型的实例中,按名称匹配属性。
您可以使用as运算符。。。这样做的好处是不会抛出异常,并且如果"强制转换"失败,您可以检查是否为null。
public class Parent
{
public string name{get;set;}
}
public class child : Parent{}
var myClass = new Child()
Parent foo = myClass as Parent
if ( foo == null ) Debug.WriteLine("foo is NOT of type Parent");
如果Parent
是Child
的超类,则Child
自动也是Parent
(包含`Parent的所有属性和方法),并且不需要强制转换。
此外,不能仅以演员阵容开始一行。你可以写例如
Parent p = (Parent)myClass;
刚刚遇到了这个问题的变体,我认为我得到了一个基于非序列化的解决方案。
像OP一样,我有从类A继承的类B,我需要B.GetType().Name返回,就好像它是类A一样。
在类B上,您需要重写GetType()以返回.GetType().BaseType
这样B.GetType()看起来总是像A.GetType(
由于这相当繁重,而且我的所有类都继承自我自己的标准基类,所以我将向返回此值的基类添加一个名为TypeName的属性。GetType().Name
然后,在我的一个特殊类上,我想让它看起来像它的父类,我会覆盖它来返回这个。GetType().BaseType.Name
然后在我的代码中,当我需要对类的类型名进行特殊的"屏蔽"时,我将引用.TypeName,而不是直接使用.GetType().Name。考虑到我只在需要忽略这个子类的一个区域中使用.GetType(),它对我自己来说是相当干净的。
我遇到了同样的问题,并提出了以下解决方案:
我最初的代码是这样的:
public class Person
{
public string Name { get; set; }
public Person() {};
public Person( Person rhs )
{
Name = rhs.Name;
}
}
public class Customer : Person
{
private string m_role = "Customer";
public string Role { get m_role; }
public Customer() : base();
}
public class Employee : Person
{
private string m_role = "Employee";
public string Role { get m_role; }
public Employee() : base();
}
当我尝试向客户投射Person对象时,我得到了"投射失败"错误
与其追求铸造的想法,我决定修改Child的复制构造函数,因此:
public class Customer : Person
{
private string m_role = "Customer";
public string Role { get m_role; }
public Customer() : base();
public Customer( Person per ) : base( per);
}
public class Employee : Person
{
private string m_role = "Employee";
public string Role { get m_role; }
public Employee () : base();
public Employee ( Person per) : base( per);
}