铸造列表< object>到列表< T>在运行时 [英] Casting List<object> to List<T> at runtime

查看:124
本文介绍了铸造列表< object>到列表< T>在运行时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图构建一个DI容器,我偶然发现了以下问题:我有一个方法来检索一个给定类型的注册实例的列表,我想使用它来注入 IEnumerable< T> 属性。我想要实现的例子如下:

I 'm trying to build a DI container and I 've stumbled on to the following problem: I have a method that retrieves a list of registered instances for a given type and I want to use that to inject IEnumerable<T> properties in a given object. An example of what I am trying to achieve would be the following:

class A { public IList<IExample> Objects { get; set; } }
class B: IExample {}
class C: IExample {}
Container.Register<IExample>(new B());
Container.Register<IExample>(new C());
var obj = new A();
Container.Inject(A);
Debug.Assert(A.Objects != null && A.Objects.Count == 2);

我的检索方法返回 IList< object> ,主要是因为我当时没有类型信息,所以我试图将该列表转换为 List< T> 在注射时。这里是一个succint形式的方法做工作:

My Retrieve method returns an IList<object>, mainly because I have no type information at that moment, so I am attempting to convert that list into a List<T> at injection time. Here is a succint form of the methods doing the work:

public virtual IList<object> Retrieve(Type type)
{
    var instances = Registry[type];
    foreach(var instance in instances) 
        Inject(type, instance); // omitted
    return instances;
}

public virtual void Inject<T>(T instance)
{
    var properties = typeof (T).GetProperties();
    foreach (var propertyInfo in properties)
    {
      var propertyType = propertyInfo.PropertyType;
      if (!IsIEnumerable(propertyType)) continue;
      var genericType = propertyType.GetGenericArguments()[0];
      propertyInfo.SetValue(instance, 
          GetListType(genericType, Retrieve(genericType)), null);
    }
}

protected virtual object GetListType(Type type, IEnumerable<object> items)
{
    return items.Select(item => Convert.ChangeType(item, type)).ToList();
}

代码返回错误: System.InvalidCastException:对象必须实现IConvertible。很遗憾,我不知道如何从这里继续。也许我这样做错了。我曾经想过使用泛型或手动注入多个属性,但我真的不想这样做。

The code returns the error: System.InvalidCastException : Object must implement IConvertible. Sadly, I don't know how to proceed from here. Perhaps I am doing this all wrong. I 've thought of using generics or injecting multiple properties by hand, but I'd really like to not have to do that.

感谢您提供任何帮助或想法。

Thanks in advance for any help or ideas.

推荐答案

可以创建如下的通用列表:

You could create a generic list like this:

public virtual IList Retrieve(Type type)
{
  // ...
  listType = typeof(List<>).MakeGenericType(new Type[] { type });
  IList list = (IList)Activator.CreateInstance(listType));
  // ...
  return list
}

列表可以转换为 IList< T> ,因为它是一个。

this list can be casted to IList<T>, because it is one.

您可以考虑使用 IEnumerable Cast< T> ,但是您没有列表的实例。我不知道有一件事有多重要。

You could consider to use IEnumerable and Cast<T>, but then you don't have an instance of a list. I don'^t know how important it is to have one.

这篇关于铸造列表&lt; object&gt;到列表&lt; T&gt;在运行时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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