在运行时将List <object>转换为List <T>

Ioa*_*mas 6 c# casting dependency-injection

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

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);
Run Code Online (Sandbox Code Playgroud)

我的Retrieve方法返回一个IList<object>,主要是因为那时我没有类型信息,所以我试图将该列表转换List<T>为注入时间.这是执行工作的方法的一种简单形式:

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();
}
Run Code Online (Sandbox Code Playgroud)

代码返回错误:System.InvalidCastException : Object must implement IConvertible.遗憾的是,我不知道如何从这里开始.也许我这样做是错的.我曾想过使用泛型或手工注入多个属性,但我真的不想这样做.

提前感谢任何帮助或想法.

Ste*_*ger 7

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

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

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

你可以考虑使用IEnumerableCast<T>,但是你没有列表的实例.我不知道拥有一个是多么重要.