序列化/反序列化动态对象
问题描述:
我有以下类别:序列化/反序列化动态对象
public abstract class Animal
{
public Animal() { _myType = getAnimal(this.GetType().Name); }
private dynamic _myType;
public dynamic myType { get { return _myType; } }
}
public class Cat : Animal
{
public Cat() : base() { }
}
而其辅助功能:
public static T CreateAnimal<T>(string animal)
{
Type type = Type.GetType(typeof(Form1).FullName + "+" + animal);
return (T)Activator.CreateInstance(type);
}
public static dynamic getAnimal(string name)
{
dynamic theAnimal = Activator.CreateInstance(MyAnimals); // Will default to 'Cat'
FieldInfo fi = MyAnimals.GetField(name);
int iEnum = (int)fi.GetValue(MyAnimals);
return Enum.ToObject(MyAnimals, iEnum);
}
因此获得了 '的myType' 从动态创建枚举 'MyAnimals':
public static Type MyAnimals;
public static void CreateAnimalEnum()
{
// Get the current application domain for the current thread.
AppDomain currentDomain = AppDomain.CurrentDomain;
// Create a dynamic assembly in the current application domain,
// and allow it to be executed and saved to disk.
AssemblyName aName = new AssemblyName("TempAssembly");
AssemblyBuilder ab = currentDomain.DefineDynamicAssembly(
aName, AssemblyBuilderAccess.Run);
// Define a dynamic module in "TempAssembly" assembly. For a single-
// module assembly, the module has the same name as the assembly.
ModuleBuilder mb = ab.DefineDynamicModule(aName.Name);
// Define a public enumeration with an underlying type of Integer.
EnumBuilder eb = mb.DefineEnum("MyAnimalType", TypeAttributes.Public, typeof(int));
var types = new List<Type>();
int Count = 0;
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
try
{
types.AddRange(assembly.GetTypes().Where(x => x.IsSubclassOf(typeof(Animal))));
}
catch { }
foreach (var type in types)
eb.DefineLiteral(type.Name, Count++);
// Create the type and save the assembly.
MyAnimals = eb.CreateType();
}
所以现在当我创建一个猫,我不能序列化它。 “InvalidOperationException:生成XML文档时发生错误。”我尝试过使用DynamicObject,并且我找到了一个动态辅助类(https://gist.github.com/martinnormark/2574972),但是当我想在封装到另一个类中时序列化一个Cat对象时,这无助于我。
public static bool Save(Animal animal)
{
System.Xml.Serialization.XmlSerializer ListSer = new System.Xml.Serialization.XmlSerializer(typeof(Animal));
System.IO.StreamWriter mywriter = new System.IO.StreamWriter(@"test.txt", false);
ListSer.Serialize(mywriter, animal);
mywriter.Flush();
mywriter.Close();
return true;
}
public Form1()
{
InitializeComponent();
GetEDIDeviceTypesEnums();
Animal c = new Cat();
Save(c);
// This way fails too
dynamic cat = CreateAnimal<Animal>("Cat");
Save(cat);
}
我为了序列化Cat而丢失了什么?
答
XMLSerializer需要提前知道它可以序列化的类型;如果你初始化一个抽象类的XMLSerializer,它只会知道如何序列化这个类而不是继承它。
XMLSerializer有另一个构造函数,它允许您输入一个额外类型的数组供其在尝试序列化时使用。您可以动态建立的类型从GetAssemblies数组(类似于你对建立自定义MyAnimals枚举什么):
public static bool Save(Animal animal)
{
var lListOfAnimals = (from lAssembly in AppDomain.CurrentDomain.GetAssemblies()
from lType in lAssembly.GetTypes()
where typeof(Animal).IsAssignableFrom(lType)
select lType).ToArray();
System.Xml.Serialization.XmlSerializer ListSer = new System.Xml.Serialization.XmlSerializer(typeof(Animal), lListOfAnimals);
代码从Yahoo Serious的回答直解禁this thread。正如Yahoo Serious提到的那样,如果经常调用Save,以这种方式使用Reflection可能会产生性能问题,因此您可能需要缓存动物类型数组,而不是每次序列化时重新构建它。
我不知道谷歌搜索你做了什么来找到这个。我现在一直在寻找一整天。非常感谢!! – Tizz 2014-08-29 18:17:09