簡體   English   中英

序列化/反序列化動態對象

[英]Serialize/Deserialize a dynamic object

我有以下課程:

    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);
    }

它從動態創建的枚舉“ MyAnimals”獲取其“ myType”:

    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認真的回答中提出。 正如Yahoo認真提到的那樣,如果您經常調用Save,則以這種方式使用Reflection可能會導致性能下降,因此您可以緩存Animal類型數組,而不是每次序列化時都對其進行重建。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM