2012-08-15 10 views
6

Ich versuche einen DI-Container zu erstellen und bin auf das folgende Problem gestoßen: Ich habe eine Methode, die eine Liste der registrierten Instanzen für einen bestimmten Typ abruft und ich möchte Verwenden Sie das, um IEnumerable<T> Eigenschaften in einem bestimmten Objekt zu injizieren.Casting Liste <object> zur Liste <T> zur Laufzeit

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); 

Meine Retrieve Methode gibt ein IList<object>, vor allem, weil ich habe keine Typinformationen in diesem Moment, so versuche ich, diese Liste in ein List<T> zu konvertieren: Ein Beispiel dafür, was ich versuche, die folgendes zu erreichen wäre zur Injektionszeit. Hier ist eine succint Form der Methoden machen die Arbeit:

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(); 
} 

Der Code gibt den Fehler: System.InvalidCastException : Object must implement IConvertible. Leider weiß ich nicht, wie man von hier zu gehen. Vielleicht mache ich das alles falsch. Ich habe daran gedacht, Generika zu verwenden oder mehrere Eigenschaften per Hand zu injizieren, aber ich möchte das wirklich nicht tun müssen.

Vielen Dank im Voraus für jede Hilfe oder Ideen.

Antwort

6

Sie können eine generische Liste wie folgt erstellen:

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

diese Liste kann IList<T> gegossen werden, denn es ist.

Sie könnten IEnumerable und Cast<T> verwenden, aber dann haben Sie keine Instanz einer Liste. Ich weiß nicht, wie wichtig es ist, einen zu haben.

+0

Das ist etwas Neues. Ich wusste nicht, dass Sie einen generischen Typ direkt erstellen könnten. Ich werde es jetzt versuchen. –

+0

Danke, es hat perfekt funktioniert! –

Verwandte Themen