c#-如何反序列化通用列表<;T>;当我不';我不知道(t)的类型?

c#-如何反序列化通用列表<;T>;当我不';我不知道(t)的类型?,c#,generics,list,ilist,serialization,C#,Generics,List,Ilist,Serialization,出于听觉原因,我使用binaryformatter将序列化的业务方法的参数存储到数据库中 问题是,当参数是泛型列表时,我找不到强制转换反序列化对象的方法,因为我不知道类型,或者如果我知道类型,我不知道如何在运行时强制转换对象 有人知道如何在运行时强制转换包含泛型列表的对象吗 我之所以需要这样做,是因为我需要在属性网格中显示反序列化的数据: object objArg = bformatter.Deserialize(memStr); //If the type is a clr type (i

出于听觉原因,我使用binaryformatter将序列化的业务方法的参数存储到数据库中

问题是,当参数是泛型列表时,我找不到强制转换反序列化对象的方法,因为我不知道类型,或者如果我知道类型,我不知道如何在运行时强制转换对象

有人知道如何在运行时强制转换包含泛型列表的对象吗

我之所以需要这样做,是因为我需要在属性网格中显示反序列化的数据:

object objArg = bformatter.Deserialize(memStr);

//If the type is a clr type (int, string, etc)
if (objArg.GetType().Module.Name == "mscorlib.dll")
{                 
    //If the type is a generic type (List<>, etc) 
    //(I'm only use List for these cases)
    if (objArg.GetType().IsGenericType)
    {
         // here is the problem
         pgArgsIn.SelectedObject = new { Value = objArg};                    

         //In the previous line I need to do something like... 
         //new { Value = (List<objArg.GetYpe()>) objArg};
     }
     else
     {
         pgArgsIn.SelectedObject = new { Value = objArg.ToString() };                    
     }
}
else
{
    //An entity object
    pgArgsIn.SelectedObject = objArg;                
}
objectobjarg=bformatter.Deserialize(memStr);
//如果类型是clr类型(int、string等)
if(objArg.GetType().Module.Name==“mscorlib.dll”)
{                 
//如果类型是泛型类型(列表等)
//(我是这些案例的唯一使用列表)
if(objArg.GetType().IsGenericType)
{
//问题就在这里
pgArgsIn.SelectedObject=new{Value=objArg};
//在前一行中,我需要做一些类似于。。。
//新的{Value=(List)objArg};
}
其他的
{
pgArgsIn.SelectedObject=new{Value=objArg.ToString()};
}
}
其他的
{
//实体对象
pgArgsIn.SelectedObject=objArg;
}

如果您使用的序列化程序没有保留类型-至少,您必须将
T
的类型与数据一起存储,并使用该类型以反射方式创建通用列表:

//during storage:
Type elementType = myList.GetType().GetGenericTypeDefinition().GetGenericArguments[0];
string typeNameToSave = elementType.FullName;

//during retrieval
string typeNameFromDatabase = GetTypeNameFromDB();
Type elementType = Type.GetType(typeNameFromDatabase);
Type listType = typeof(List<>).MakeGenericType(new Type[] { elementType });
//存储期间:
Type elementType=myList.GetType().GetGenericTypeDefinition().GetGenericArguments[0];
字符串typeNameToSave=elementType.FullName;
//检索期间
字符串typeNameFromDatabase=GetTypeNameFromDB();
Type elementType=Type.GetType(typeNameFromDatabase);
Type listType=typeof(List).MakeGenericType(新类型[]{elementType});

现在您有了
listType
,这正是您使用的
List
(例如,
List
)。您可以将该类型传递到反序列化例程。

使用
BinaryFormatter
您不需要知道该类型;元数据包含在流中(使其更大,但嘿!)。但是,除非您知道类型,否则无法强制转换。通常在这种情况下,您必须使用常见的已知接口(非泛型
IList
等)和反射。而且很多

我也不认为需要知道在
PropertyGrid
中显示的类型有多大要求-因为它接受
对象
,只需按照
BinaryFormatter
提供的内容来设置即可。你在那里看到的是一个具体的问题吗?同样,您可能希望检查
IList
(非泛型)-但不值得担心
IList
,因为这不是
PropertyGrid
检查的内容

当然,如果需要(),您可以找到
T
,并使用
MakeGenericType()
Activator.CreateInstance
——这并不漂亮


嗯,;这里有一种使用自定义描述符的方法,不涉及对对象或列表类型的任何了解;如果你真的想把列表项直接扩展到属性中,那么在这个例子中你会看到两个假属性(“Fred”和“Wilma”)——这是额外的工作-p

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;

class Person
{
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }

    public override string ToString() {
        return Name;
    }
}

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Person fred = new Person();
        fred.Name = "Fred";
        fred.DateOfBirth = DateTime.Today.AddYears(-23);
        Person wilma = new Person();
        wilma.Name = "Wilma";
        wilma.DateOfBirth = DateTime.Today.AddYears(-20);

        ShowUnknownObject(fred, "Single object");
        List<Person> list = new List<Person>();
        list.Add(fred);
        list.Add(wilma);
        ShowUnknownObject(list, "List");
    }
    static void ShowUnknownObject(object obj, string caption)
    {
        using(Form form = new Form())
        using (PropertyGrid grid = new PropertyGrid())
        {
            form.Text = caption;
            grid.Dock = DockStyle.Fill;
            form.Controls.Add(grid);
            grid.SelectedObject = ListWrapper.Wrap(obj);
            Application.Run(form);
        }
    }
}

[TypeConverter(typeof(ListWrapperConverter))]
public class ListWrapper
{
    public static object Wrap(object obj)
    {
        IListSource ls = obj as IListSource;
        if (ls != null) obj = ls.GetList(); // list expansions

        IList list = obj as IList;
        return list == null ? obj : new ListWrapper(list);
    }
    private readonly IList list;
    private ListWrapper(IList list)
    {
        if (list == null) throw new ArgumentNullException("list");
        this.list = list;
    }
    internal class ListWrapperConverter : TypeConverter
    {
        public override bool GetPropertiesSupported(ITypeDescriptorContext context)
        {
            return true;
        }
        public override PropertyDescriptorCollection GetProperties(
            ITypeDescriptorContext context, object value, Attribute[] attributes) {
            return new PropertyDescriptorCollection(
                new PropertyDescriptor[] { new ListWrapperDescriptor(value as ListWrapper) });
        }
    }
    internal class ListWrapperDescriptor : PropertyDescriptor {
        private readonly ListWrapper wrapper;
        internal ListWrapperDescriptor(ListWrapper wrapper) : base("Wrapper", null)
        {
            if (wrapper == null) throw new ArgumentNullException("wrapper");
            this.wrapper = wrapper;
        }
        public override bool ShouldSerializeValue(object component) { return false; }
        public override void ResetValue(object component) {
            throw new NotSupportedException();
        }
        public override bool CanResetValue(object component) { return false; }
        public override bool IsReadOnly {get {return true;}}
        public override void SetValue(object component, object value) {
            throw new NotSupportedException();
        }
        public override object GetValue(object component) {
            return ((ListWrapper)component).list;
        }
        public override Type ComponentType {
            get { return typeof(ListWrapper); }
        }
        public override Type PropertyType {
            get { return wrapper.list.GetType(); }
        }
        public override string DisplayName {
            get {
                IList list = wrapper.list;
                if (list.Count == 0) return "Empty list";

                return "List of " + list.Count
                    + " " + list[0].GetType().Name;
            }
        }
    }
}
使用系统;
使用系统集合;
使用System.Collections.Generic;
使用系统组件模型;
使用System.Windows.Forms;
班主任
{
公共字符串名称{get;set;}
公共日期时间出生日期{get;set;}
公共重写字符串ToString(){
返回名称;
}
}
静态类程序
{
[状态线程]
静态void Main()
{
Application.EnableVisualStyles();
Person fred=新的Person();
fred.Name=“fred”;
fred.DateOfBirth=DateTime.Today.AddYears(-23);
Person-wilma=新的Person();
wilma.Name=“wilma”;
wilma.DateOfBirth=DateTime.Today.AddYears(-20);
ShowUnknownObject(弗雷德,“单个对象”);
列表=新列表();
增加(弗雷德);
列表。添加(威尔玛);
ShowUnknownObject(列表,“列表”);
}
静态void ShowUnknownObject(对象对象,字符串标题)
{
使用(表单=新表单())
使用(PropertyGrid grid=new PropertyGrid())
{
form.Text=标题;
grid.Dock=DockStyle.Fill;
表单.控件.添加(网格);
grid.SelectedObject=ListWrapper.Wrap(obj);
申请表格;
}
}
}
[TypeConverter(typeof(ListWrapperConverter))]
公共类ListWrapper
{
公共静态对象包裹(对象obj)
{
IListSource ls=对象作为IListSource;
如果(ls!=null)obj=ls.GetList();//列表扩展
IList列表=对象作为IList;
返回列表==null?obj:新的ListWrapper(列表);
}
私有只读IList列表;
私有ListWrapper(IList列表)
{
如果(list==null)抛出新的ArgumentNullException(“list”);
this.list=列表;
}
内部类ListWrapperConverter:TypeConverter
{
公共覆盖布尔GetPropertiesSupported(ITypeDescriptorContext上下文)
{
返回true;
}
公共重写属性DescriptorCollection GetProperties(
ITypeDescriptorContext上下文、对象值、属性[]属性){
返回新属性DescriptorCollection(
新的PropertyDescriptor[]{new ListWrapperDescriptor(值为ListWrapper)};
}
}
内部类ListWrapperDescriptor:PropertyDescriptor{
私有只读列表包装器;
内部ListWrapperDescriptor(ListWrapper):基本(“包装器”,null)
{
如果(wrapper==null)抛出新的ArgumentNullException(“wrapper”);
this.wrapper=包装器;
}
公共覆盖布尔值应为