也许您可以使用基类而不是接口并将其序列化。
更新
我意识到使用基类对你来说并不是一个真正的选择。
最好的解决方案可能是像 Henk Holterman 所说的那样使用 DTO 来解决问题。
但是,如果您真的想要解决您的问题,我认为您必须创建自己的自定义序列化程序,但我不建议您这样做,因为您最终会遇到很多错误需要解决。
这是自定义序列化程序的示例,请记住,此示例需要一些工作才能在实际应用程序中完全使用。
至少必须添加两件事才能使其不仅仅是一个示例:
- 异常处理
- 将 xml 元素值转换或转换为正确的类型
anyThingProperty.SetValue(obj, propertyElement.Value, null);
[TestClass]
public class SerializableInterfaceTest
{
[TestMethod]
public void TestMethod1()
{
string serialize = AnyThingSerializer.Serialize(
new SerializableClass {Name = "test", Description = "test1",
AnyThing = new Animal {Name = "test", Color = "test1"}});
Console.WriteLine(serialize);
object obj = AnyThingSerializer.Deserialize(serialize);
}
}
public sealed class SerializableClass
{
public string Name { get; set; }
public string Description { get; set; }
[AnyThingSerializer]
public object AnyThing { get; set; }
}
public static class AnyThingSerializer
{
public static string Serialize(object obj)
{
Type type = obj.GetType();
var stringBuilder = new StringBuilder();
var serializer = new XmlSerializer(type);
serializer.Serialize(new StringWriter(stringBuilder), obj);
XDocument doc = XDocument.Load(new StringReader(stringBuilder.ToString()));
foreach (XElement xElement in SerializeAnyThing(obj))
{
doc.Descendants().First().Add(xElement);
}
return doc.ToString();
}
public static object Deserialize(string xml)
{
var serializer = new XmlSerializer(typeof (T));
object obj = serializer.Deserialize(new StringReader(xml));
XDocument doc = XDocument.Load(new StringReader(xml));
DeserializeAnyThing(obj, doc.Descendants().OfType().First());
return obj;
}
private static void DeserializeAnyThing(object obj, XElement element)
{
IEnumerable anyThingProperties = obj.GetType()
.GetProperties().Where(p => p.GetCustomAttributes(true)
.FirstOrDefault(a => a.GetType() ==
typeof (AnyThingSerializerAttribute)) != null);
foreach (PropertyInfo anyThingProperty in anyThingProperties)
{
XElement propertyElement = element.Descendants().FirstOrDefault(e =>
e.Name == anyThingProperty.Name && e.Attribute("type") != null);
if (propertyElement == null) continue;
Type type = Type.GetType(propertyElement.Attribute("type").Value);
if (IsSimpleType(type))
{
anyThingProperty.SetValue(obj, propertyElement.Value, null);
}
else
{
object childObject = Activator.CreateInstance(type);
DeserializeAnyThing(childObject, propertyElement);
anyThingProperty.SetValue(obj, childObject, null);
}
}
}
private static List SerializeAnyThing(object obj)
{
var doc = new List();
IEnumerable anyThingProperties =
obj.GetType().GetProperties().Where(p =>
p.GetCustomAttributes(true).FirstOrDefault(a =>
a.GetType() == typeof (AnyThingSerializerAttribute)) != null);
foreach (PropertyInfo anyThingProperty in anyThingProperties)
{
doc.Add(CreateXml(anyThingProperty.Name,
anyThingProperty.GetValue(obj, null)));
}
return doc;
}
private static XElement CreateXml(string name, object obj)
{
var xElement = new XElement(name);
Type type = obj.GetType();
xElement.Add(new XAttribute("type", type.AssemblyQualifiedName));
foreach (PropertyInfo propertyInfo in type.GetProperties())
{
object value = propertyInfo.GetValue(obj, null);
if (IsSimpleType(propertyInfo.PropertyType))
{
xElement.Add(new XElement(propertyInfo.Name, value.ToString()));
}
else
{
xElement.Add(CreateXml(propertyInfo.Name, value));
}
}
return xElement;
}
private static bool IsSimpleType(Type type)
{
return type.IsPrimitive || type == typeof (string);
}
}
public class AnyThingSerializerAttribute : XmlIgnoreAttribute
{
}