Не знаю, сработает ли это, но попробуйте изменить его на:
XmlSerializer xs = new XmlSerializer(typeof(T));
это скажет сериализатору создать экземпляр сериализатора любого типа, который вы укажете. Хотя я не уверен, что сериализатор это сделает.
Изменить: При условии, что вы звоните
SerializeGeneric<MyClass1>(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; }
}
Выдает исключение «Неожиданный тип». Оказывается, сериализатор не будет сериализовать объект как другой тип. Не уверен, что это можно сделать.
Полагаю, вы могли бы написать собственный сериализатор или написать простой метод отражения, который выполняет операцию memberwiseclone-ish, которая копирует только те свойства из foo1, которые вы хотите.
Интересно, что если вы добавите [XmlInclude (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>
Это объявление 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;
}
Это дает вам:
<Foo1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Prop1>Test</Prop1>
</Foo1>
, который выглядит идеально.