序列化泛型类型列表 [英] serialize list of generic type

查看:154
本文介绍了序列化泛型类型列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个用于保存任何数据类型的泛型列表的序列化应用程序。因此,我设计了一个base-DataType来填充列表,如下所示:

  public abstract class GenericObject< T> {
公共字符串键;
公共T值;

public GenericObject(){}
public GenericObject(string key,T value):this(){
this.key = key;
this.value = value;


此外还有一个类 GenericList 实现 IXmlSerializable - 接口来编写键值对,如下所示:

  GenericObject< INT> myInt = new GenericObject< int>(key,3); 

这将生成以下XML:

 <键→3< /密钥GT; 

GenericList 的类定义是或多或少地如下所示:

  public class GenericList< T> :IXmlSerializable {
List< T>对象;
// ...
}

所以我们假设我们有一个从 GenericObject< string> (不管它看起来如何)的派生类 Person ,并且我们要填充与几个人列表。我遇到的问题是在 GenericList - 类的泛型类型T上定义一个约束,以便只有从 GenericObject 。我已经尝试过使用 public class GenericList< T> :IXmlSerializable其中T:GenericObject< object> 但由于以下编译器错误而无法工作:

  Person'不能在通用类型或方法'GenericList< T>'中用作类型参数'T'。没有从'Person'到'GenericObject< object>'的隐式引用转换'

我也试过留下where子句为空,但是我必须检查 GenericList 中的 T 类型以获得它的关键和价值,我也失败了,如下所示:

  if(typeof(T).IsAssignableFrom(typeof(GenericObject< object> ;))

它总是会返回false作为 T 是Person类型而不是 GenericObject< object>



有没有人可以提供一些建议用我的名单填写我的名单? en-us / library / ee207183.aspxrel =nofollow>协方差。由于变体类型参数只能在接口和委托中声明(不在类定义中),所以还需要定义一个接口:

  public interface IGenericObject< out T> 
{
string Key {get; }
T值{get; }
}

公共抽象类GenericObject< T> :IGenericObject< T>
{
public string Key {get;组; }
public T Value {get;组; }

保护GenericObject(){}

保护GenericObject(字符串键,T值)
:this()
{
this .Key = key;
this.Value = value;
}
}

public class GenericList< TGenericObject> :IXmlSerializable
其中TGenericObject:IGenericObject< object>
{
private只读列表< TGenericObject> _list = new List< TGenericObject>();

public void Add(TGenericObject item)
{
_list.Add(item);

$ b $ public XmlSchema GetSchema()
{
// ...
}

public void ReadXml(XmlReader阅读器)
{
// ...
}

public void WriteXml(XmlWriter writer)
{
// ...
}
}

public class Person:GenericObject< string>
{

}

现在你可以这样做:

  public class SomeClass 
{
public void SomeMethod()
{
Person somePerson = new Person();

GenericList< IGenericObject< object>> listWithGenericsOfObject = new GenericList< IGenericObject< object>>();
listWithGenericsOfObject.Add(somePerson);

GenericList< IGenericObject< string>> listWithGenericsOfString = new GenericList< IGenericObject< string>>();
listWithGenericsOfString.Add(somePerson);

GenericList< Person> listWithGenericsOfPerson = new GenericList< Person>();
listWithGenericsOfPerson.Add(somePerson);


$ / code $ / pre

现在你不需要检查类型运行时使用IsAssignableFrom。但是,如果您需要它,您应该像这样交换类型:

  typeof(GenericObject< object>)。IsAssignableFrom (typeof(T))


I am writing an application for serialization of a generic List that holds any datatype.So I designed a base-DataType to fill the list with as follows:

public abstract class GenericObject<T> {
    public string key;
    public T value;

    public GenericObject() { }
    public GenericObject(string key, T value) : this() { 
        this.key = key;
        this.value = value;
    }
}

Furthermore there is a class GenericList which implements the IXmlSerializable-Interface to write a key-value pair as like this:

GenericObject<int> myInt = new GenericObject<int>("key", 3);

Which will produce the following XML:

<key>3</key>

The class-definition for the GenericList is more or less as follows:

public class GenericList<T> : IXmlSerializable {
    List<T> objects;
    // ...
}

So let´s assume we have a class Person that derives from GenericObject<string>(no matter how it looks like) and we want to fill the list with a couple of persons. The problem I have is defining a constraint on the generic type T of the GenericList-class so that only types are possible that derive from GenericObject. I already tried it by using public class GenericList<T> : IXmlSerializable where T : GenericObject<object> but that did not work because of the following compiler error:

Person' cannot be used as type parameter 'T' in the generic type or method 'GenericList<T>'. There is no implicit reference conversion from 'Person' to 'GenericObject<object>'

I also tried out leaving the where-clause empty, but then I have to check the type of T within the GenericList in order to get its key and value where I also failed with the following:

if (typeof(T).IsAssignableFrom(typeof(GenericObject<object>))) 

which will always return false as T is of type Person and not GenericObject<object>.

May anyone have some suggestion how I can fill my list with a person?

解决方案

You can use covariance. Since variant type parameters only can be declared in interfaces and delegates (not in class definitions), you also need to define an interface:

public interface IGenericObject<out T>
{
    string Key { get; }
    T Value { get; }
}

public abstract class GenericObject<T> : IGenericObject<T>
{
    public string Key { get; set; }
    public T Value { get; set; }

    protected GenericObject() { }

    protected GenericObject(string key, T value)
        : this()
    {
        this.Key = key;
        this.Value = value;
    }
}

public class GenericList<TGenericObject> : IXmlSerializable
    where TGenericObject : IGenericObject<object>
{
    private readonly List<TGenericObject> _list = new List<TGenericObject>();

    public void Add(TGenericObject item)
    {
        _list.Add(item);
    }

    public XmlSchema GetSchema()
    {
        // ...
    }

    public void ReadXml(XmlReader reader)
    {
        // ...
    }

    public void WriteXml(XmlWriter writer)
    {
        // ...
    }
}

public class Person : GenericObject<string>
{

}

Now you can do this:

public class SomeClass
{
    public void SomeMethod()
    {
        Person somePerson = new Person();

        GenericList<IGenericObject<object>> listWithGenericsOfObject = new GenericList<IGenericObject<object>>();
        listWithGenericsOfObject.Add(somePerson);

        GenericList<IGenericObject<string>> listWithGenericsOfString = new GenericList<IGenericObject<string>>();
        listWithGenericsOfString.Add(somePerson);

        GenericList<Person> listWithGenericsOfPerson = new GenericList<Person>();
        listWithGenericsOfPerson.Add(somePerson);
    }
}

Now you don't need to check the type at runtime using IsAssignableFrom. However, in case you will need it, you should swap the types like this:

typeof(GenericObject<object>).IsAssignableFrom(typeof(T))

这篇关于序列化泛型类型列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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