C# 泛型和XmlSerializer的继承转换问题
如何强制转换对象的实例并使其成为该类型的对象 我有一个类myClass1,它是myClass2和myClass3的基类。我想用myClass1进行审计,因为我只想审计myClass1中的数据。因为myClass2和myClass3继承自myClass1,所以可以将myClass1的实例设置为myClass2的实例示例:C# 泛型和XmlSerializer的继承转换问题,c#,generics,xml-serialization,casting,C#,Generics,Xml Serialization,Casting,如何强制转换对象的实例并使其成为该类型的对象 我有一个类myClass1,它是myClass2和myClass3的基类。我想用myClass1进行审计,因为我只想审计myClass1中的数据。因为myClass2和myClass3继承自myClass1,所以可以将myClass1的实例设置为myClass2的实例示例: myClass2 foo = new myClass2(); foo.prop1 = "some data"; foo.prop2 = "some More Data"; my
myClass2 foo = new myClass2();
foo.prop1 = "some data";
foo.prop2 = "some More Data";
myClass1 bar = foo;
问题的出现是因为我使用的是泛型
public static IXPathNavigable SerializeGeneric<T>(T serializableObject)
{
String XmlizedString = "Error processing request";
XmlDocument XMLObject = new XmlDocument();
try
{
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xs = new XmlSerializer(serializableObject.GetType());
name的值是“myClass2”,这很有意义,因为内存中的数据实际上是一个myClass2,而条下面只是一个指向myClass2对象的指针。无需创建新实例并将该新实例的值设置为该对象,如
myClass1 bar = new myClass1(){prop1=foo.prop1, prop2=foo.prop2};
我真的不想这样做。不知道这是否可行,但请尝试将其更改为:
XmlSerializer xs = new XmlSerializer(typeof(T));
这将告诉序列化程序创建您指定的任何类型的序列化程序实例。虽然我不确定序列化程序是否会这样做
编辑:只要你打电话
SerializeGeneric<MyClass1>(foo);
SerializeGeneric(foo);
再次编辑:
就用这个试过了:
public void Test()
{
var obj = new Foo2() { Prop1 = "Test", Prop2 = "Test2" };
SerializeGeneric((Foo1)obj);
}
private void SerializeGeneric<T>(T obj)
{
StringWriter writer = new StringWriter();
XmlSerializer xs = new XmlSerializer(typeof(T));
xs.Serialize(writer, obj);
Console.WriteLine(writer.ToString());
}
public class Foo1
{
public string Prop1 { get; set; }
}
public class Foo2 : Foo1
{
public string Prop2 { get; set; }
}
公共无效测试()
{
var obj=newfoo2(){Prop1=“Test”,Prop2=“Test2”};
序列化通用((Foo1)obj);
}
私有对象(T obj)
{
StringWriter编写器=新的StringWriter();
XmlSerializer xs=新的XmlSerializer(typeof(T));
序列化(writer,obj);
Console.WriteLine(writer.ToString());
}
公开课1
{
公共字符串Prop1{get;set;}
}
公共类Foo2:Foo1
{
公共字符串Prop2{get;set;}
}
它抛出一个“意外类型”的异常。事实证明,序列化程序不会将对象序列化为其他类型。我不确定有什么办法能让它做到
我想您可以编写一个自定义序列化程序,或者编写一个简单的反射方法来执行memberwiseclone-ish操作,该操作只复制您想要的foo1中的属性
有趣的是,如果将[xmlclude(typeof(Foo2))]添加到Foo1声明中,则不会出现错误,尽管它会输出以下胡言乱语:
<Foo1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="Foo2">
<Prop1>Test</Prop1>
<Prop2>Test2</Prop2>
</Foo1>
试验
测试2
这是一个Foo1声明,具有Foo1和Foo2属性,类型声明为Foo2。。。有趣
最后一个:
这很管用,不过我不确定我会推荐它
public void Test ()
{
var obj = new Foo2() { Prop1 = "Test", Prop2 = "Test2" };
SerializeGeneric(ShallowCopy<Foo1>(obj));
}
private T ShallowCopy<T>(object input)
where T : class, new()
{
T newObj = Activator.CreateInstance<T>();
Type oldType = input.GetType();
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField | BindingFlags.SetField;
var oldProperties = oldType.GetProperties(flags);
foreach (var pd in typeof(T).GetProperties(flags))
{
var oldPd = oldProperties.FirstOrDefault(x=>x.Name == pd.Name && x.PropertyType == pd.PropertyType);
if(oldPd != null)
pd.SetValue(newObj, oldPd.GetValue(input, null), null);
}
return newObj;
}
公共无效测试()
{
var obj=newfoo2(){Prop1=“Test”,Prop2=“Test2”};
一般(浅镜(obj));
}
私有T浅拷贝(对象输入)
其中T:class,new()
{
T newObj=Activator.CreateInstance();
Type oldType=input.GetType();
BindingFlags flags=BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField | BindingFlags.SetField;
var oldProperties=oldType.GetProperties(标志);
foreach(typeof(T).GetProperties(flags)中的varpd)
{
var oldPd=oldProperties.FirstOrDefault(x=>x.Name==pd.Name&&x.PropertyType==pd.PropertyType);
如果(oldPd!=null)
pd.SetValue(newObj,oldp.GetValue(输入,null),null);
}
返回newObj;
}
这将为您提供:
<Foo1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Prop1>Test</Prop1>
</Foo1>
试验
看起来很完美。不知道这是否有效,但请尝试将其更改为:
XmlSerializer xs = new XmlSerializer(typeof(T));
这将告诉序列化程序创建您指定的任何类型的序列化程序实例。虽然我不确定序列化程序是否会这样做
编辑:只要你打电话
SerializeGeneric<MyClass1>(foo);
SerializeGeneric(foo);
再次编辑:
就用这个试过了:
public void Test()
{
var obj = new Foo2() { Prop1 = "Test", Prop2 = "Test2" };
SerializeGeneric((Foo1)obj);
}
private void SerializeGeneric<T>(T obj)
{
StringWriter writer = new StringWriter();
XmlSerializer xs = new XmlSerializer(typeof(T));
xs.Serialize(writer, obj);
Console.WriteLine(writer.ToString());
}
public class Foo1
{
public string Prop1 { get; set; }
}
public class Foo2 : Foo1
{
public string Prop2 { get; set; }
}
公共无效测试()
{
var obj=newfoo2(){Prop1=“Test”,Prop2=“Test2”};
序列化通用((Foo1)obj);
}
私有对象(T obj)
{
StringWriter编写器=新的StringWriter();
XmlSerializer xs=新的XmlSerializer(typeof(T));
序列化(writer,obj);
Console.WriteLine(writer.ToString());
}
公开课1
{
公共字符串Prop1{get;set;}
}
公共类Foo2:Foo1
{
公共字符串Prop2{get;set;}
}
它抛出一个“意外类型”的异常。事实证明,序列化程序不会将对象序列化为其他类型。我不确定有什么办法能让它做到
我想您可以编写一个自定义序列化程序,或者编写一个简单的反射方法来执行memberwiseclone-ish操作,该操作只复制您想要的foo1中的属性
有趣的是,如果将[xmlclude(typeof(Foo2))]添加到Foo1声明中,则不会出现错误,尽管它会输出以下胡言乱语:
<Foo1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="Foo2">
<Prop1>Test</Prop1>
<Prop2>Test2</Prop2>
</Foo1>
试验
测试2
这是一个Foo1声明,具有Foo1和Foo2属性,类型声明为Foo2。。。有趣
最后一个:
这很管用,不过我不确定我会推荐它
public void Test ()
{
var obj = new Foo2() { Prop1 = "Test", Prop2 = "Test2" };
SerializeGeneric(ShallowCopy<Foo1>(obj));
}
private T ShallowCopy<T>(object input)
where T : class, new()
{
T newObj = Activator.CreateInstance<T>();
Type oldType = input.GetType();
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField | BindingFlags.SetField;
var oldProperties = oldType.GetProperties(flags);
foreach (var pd in typeof(T).GetProperties(flags))
{
var oldPd = oldProperties.FirstOrDefault(x=>x.Name == pd.Name && x.PropertyType == pd.PropertyType);
if(oldPd != null)
pd.SetValue(newObj, oldPd.GetValue(input, null), null);
}
return newObj;
}
公共无效测试()
{
var obj=newfoo2(){Prop1=“Test”,Prop2=“Test2”};
一般(浅镜(obj));
}
私有T浅拷贝(对象输入)
其中T:class,new()
{
T newObj=Activator.CreateInstance();
Type oldType=input.GetType();
BindingFlags flags=BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField | BindingFlags.SetField;
var oldProperties=oldType.GetProperties(标志);
foreach(typeof(T).GetProperties(flags)中的varpd)
{
var oldPd=oldProperties.FirstOrDefault(x=>x.Name==pd.Name&&x.PropertyType==pd.PropertyType);
如果(oldPd!=null)
pd.SetValue(newObj,oldp.GetValue(输入,null),null);
}
返回newObj;
}
这将为您提供:
<Foo1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Prop1>Test</Prop1>
</Foo1>
试验
这看起来很完美。要在继承时正确执行xml序列化,有两条准则:
typeof(Base)
(序列化或反序列化时)创建XmlSerializer