C#中的Serialise接口 [英] Serialise interfaces in C#

查看:95
本文介绍了C#中的Serialise接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的我知道这是完全可能的。但是.....我有一个班级说List< IPerson> IPerson是一个接口。我想序列化这个类来存储状态。



除了实现IXmlSerializable并自己完成之外,还有什么简单的方法。这看起来确实相当繁重。



或许有人有任何实现IXmlSerializable的好例子吗?



不使用接口不是一个选项!



我尝试过:



实现IXmlSerializable并完成一个完整的混乱!

Ok I know it's strictly possible. But.....I have a class with say a List<IPerson> where IPerson is an interface. I want to serialize this class to store state.

Is there any simple way apart from implementing IXmlSerializable and doing it all yourself. This seems rather onerous indeed.

Alternatively does anyone have any good example of implementing IXmlSerializable to achieve this?

Not using interfaces is not an option!

What I have tried:

Implementing IXmlSerializable and getting in a complete and utter mess!

推荐答案

序列化之后,反序列化。由于您无法实例化接口,因此需要一个具体的类(实现该接口) - 现在出现了一个难题:您想在这里使用哪个类?

问题类似于抽象类和继承自它们的类。例如。继承自(抽象)动物的狗和猫。

最后,您只能使用具体类进行序列化/反序列化。想象一下Dog序列化为Animal,并反序列化为Cat ...
Somewhen after serialization, comes de-serialization. Since you cannot instantiate an interface, a concrete class (implementing that interface) is required - and now comes the difficult question: what class do you want to use here?
The problem is similar with abstract classes and classes inheriting from them. E.g. Dog and Cat inheriting from (abstract) Animal.
In the end, you can only use concrete classes for serialization / de-serialization. Just imagine a Dog serialized as Animal, and de-serialized as Cat...


让我举一个工作示例来证明接口的实例可以被序列化。请注意,当我说接口实例时,我的意思是您已经从一个接口继承了某些类的有效实例,并将这些实例强制转换为它们的接口形式。当然,当您保存这样的接口实例时,不保存接口中未指定的类(字段,属性)元素。



一个人为的例子,展示了所涉及的技术;为了让这个更有趣......对我而言,我还将演示如何序列化静态类的静态成员(不,你不能序列化静态类本身):
Let me give you a working example to prove that instances of Interfaces can be serialized. Note that when I say "instances of Interfaces" I mean you have taken valid instances of some Class that inherited from an Interface and cast those instances into their "Interface Form." Naturally, when you save some "interface instance" like this, you do not save the elements of the Class (Fields, Properties) that are not specified in the Interface.

A contrived example demonstrating the techniques involved; to make this "more interesting ... for me", I will also demonstrate how to serialize a static Member of a Static Class (no, you cannot serialize a Static Class itself):
namespace YourNameSpace
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Runtime.Serialization;

    public interface IAnimal
    {
        Species AnimalSpecies { set; get; }
    }

    public interface ISpecies
    {
        string SpeciesName { set; get; }
    }

    [DataContract]
    public class Species : ISpecies
    {
        [DataMember]
        public string SpeciesName { get; set; }

        public Species(string speciesName)
        {
            SpeciesName = speciesName;
        }
    }

    [DataContract]
    public class Animal : IAnimal
    {
        [DataMember]
        public Species AnimalSpecies { set; get; }

        public Animal(string speciesName)
        {
            AnimalSpecies = new Species(speciesName);
        }
    }

    [DataContract]
    public class Dog : Animal
    {
        [DataMember]
        public string DogName { set; get; }

        public Dog(string dogName, string speciesName) : base(speciesName)
        {
            DogName = dogName;
        }
    }

    [DataContract]
    public class Cat : Animal
    {
        [DataMember]
        public string CatName { set; get; }

        public Cat(string speciesName, string catName) : base(speciesName)
        {
            CatName = catName;
        }
    }

    [DataContract]
    public static class MyAnimals
    {
        [DataMember]
        public static List<Animal> TheAnimals { set; get; }

        [DataMember]
        public static List<IAnimal> TheIAnimals { set; get; }

        static MyAnimals()
        {
            TheAnimals = new List<Animal>();
            TheIAnimals = new List<IAnimal>();
        }
    }

    [DataContract]
    public class MyCats
    {
        [DataMember]
        private List<Cat> MyCatCollection { set; get; }

        public MyCats()
        {
            MyCatCollection = new List<Cat>();
        }

        public void AddCat(Cat theCat)
        {
            MyCatCollection.Add(theCat);
            MyAnimals.TheAnimals.Add(theCat);
            MyAnimals.TheIAnimals.Add(theCat);
        }
    }

    [DataContract]
    public class MyDogs
    {
        [DataMember]
        private List<Dog> MyDogCollection { set; get; }

        public MyDogs()
        {
            MyDogCollection = new List<Dog>();
        }

        public void AddDog(Dog theDog)
        {
            MyDogCollection.Add(theDog);
            MyAnimals.TheAnimals.Add(theDog);
            MyAnimals.TheIAnimals.Add(theDog);
        }
}

请注意,每次添加新的Dog或Cat类实例时,它们的构造函数都会将对新类的引用添加到两个静态集合(通用列表)中。 static类名为'MyAnimals。新的Dog或Cat实例被添加到'Animal Type'的列表中,以及'IAnimal Type'的列表。



因此,假设您创建了一些实例这个类结构:

Note that every time you add a 'new Dog or Cat Class instance their constructors add the reference to the new Class to two static collections (generic lists) in a static Class named 'MyAnimals. The new Dog or Cat instance is added to a list of the 'Animal Type, and a list of the 'IAnimal Type.

So let's say you create some instances of this Class structure:

// in some Method or EventHandler
MyCats myCats = new MyCats();
myCats.AddCat(new Cat("felix", "HisRoyalMeow"));
myCats.AddCat(new Cat("felix", "HerRoyalMeow"));

MyDogs myDogs = new MyDogs();
myDogs.AddDog(new Dog("Lab", "LikesToBeWet"));
myDogs.AddDog(new Dog("Chihuahua", "Mr. Sausage"));

您需要做什么来序列化和反序列化存储的Cat和Dog实例列表在他们的'静态类中的IAnimal形式'MyAnimals:

What you need to do to serialize and de-serialize the List of instances of Cat and Dog stored in their 'IAnimal form in the static Class 'MyAnimals:

public static class SaveTheAnimals
{
    private static DataContractSerializer _dcs;

    public static string filePath = @"C:\Users\YourUserName\Desktop\test\SomeAnimals.xml";

    public static void SerializeMyAnimals()
    {
         // see note below
        _dcs = new DataContractSerializer(typeof(List<IAnimal>), new List<Type>{typeof(Cat), typeof(Dog)});

        using (FileStream fs = new FileStream(filePath, FileMode.Create))
        {
            _dcs.WriteObject(fs, MyAnimals.TheIAnimals);
        }
    }

    public static List<IAnimal> DeSerializeMyAnimals()
    {
        _dcs = new DataContractSerializer(typeof(List<IAnimal>), new List<Type> { typeof(Cat), typeof(Dog) });

        List<IAnimal> myAnimals;

        using (FileStream fs = new FileStream(filePath, FileMode.Open))
        {
            myAnimals = (List<IAnimal>)_dcs.ReadObject(fs);
        }

        return myAnimals;
    }
}

注意:



1.这个工作的原因是提供新的实例DataContract Serializer一个已知类型列表供它使用。您将注意到,您还可以使用您希望它知道的每个类型的'KnownType属性来装饰DataContract类...但是,在这种情况下......静态类......不起作用(不要问我为什么)...并且在构造时必须向序列化器提供已知类型列表。



2.查看实际的XML通过保存List< IAnimal>生成

Notes:

1. What makes this "work" is providing the new instance of the DataContract Serializer a list of "known Types" for it to work with. You will note that you can also decorate a DataContract Class with the 'KnownType Attribute for each Type you wish it to be "aware of" ... however, in this case ... a Static Class ... that would not work (don't ask me why) ... and you must provide the list of Known Types to the serializer when you construct it.

2. Look at the actual XML produced by saving the List<IAnimal>

<ArrayOfanyType xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
	<anyType i:type="a:Cat" xmlns:a="http://schemas.datacontract.org/2004/07/June6AutoForm">
		<a:AnimalSpecies>
			<a:SpeciesName>felix</a:SpeciesName>
		</a:AnimalSpecies>
		<a:CatName>HisRoyalMeow</a:CatName>
	</anyType>
	<anyType i:type="a:Cat" xmlns:a="http://schemas.datacontract.org/2004/07/June6AutoForm">
		<a:AnimalSpecies>
			<a:SpeciesName>felix</a:SpeciesName>
		</a:AnimalSpecies>
		<a:CatName>HerRoyalMeow</a:CatName>
	</anyType>
	<anyType i:type="a:Dog" xmlns:a="http://schemas.datacontract.org/2004/07/June6AutoForm">
		<a:AnimalSpecies>
			<a:SpeciesName>LikesToBeWet</a:SpeciesName>
		</a:AnimalSpecies>
		<a:DogName>Lab</a:DogName>
	</anyType>
	<anyType i:type="a:Dog" xmlns:a="http://schemas.datacontract.org/2004/07/June6AutoForm">
		<a:AnimalSpecies>
			<a:SpeciesName>Mr. Sausage</a:SpeciesName>
		</a:AnimalSpecies>
		<a:DogName>Chihuahua</a:DogName>
	</anyType>
</ArrayOfanyType>

请注意,每个条目不仅包含您期望的SpeciesName,还包含'DogName或'CatName信息。并且,请问微软为什么这样做:)因为如果你把一个特定的'狗或'猫投射到它的IAnimal表格,你不应该看到这些信息。

Note that each entry contains not only the SpeciesName, which you would expect, but, also, the 'DogName or 'CatName information. And, please ask Microsoft why this works :) because if you cast a specific 'Dog or 'Cat to its IAnimal Form, you should not see that information.


请学习最好和最简单的在.NET中使用序列化方法,数据合同:使用数据合同



注意,接口序列化的概念毫无意义。 Interfaced不包含数据(仅元数据)。



-SA
Please learn the best and easiest to use serialization approach in .NET, Data Contract: Using Data Contracts.

Note, the notion of serialization of interface makes no sense. Interfaced don't contain data (only metadata).

—SA


这篇关于C#中的Serialise接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆