2009-07-27 14 views
28

Jak mogę rozwiązać problem SomeInstance w autofac, biorąc pod uwagę poniższy kod?Rozwiązywanie ogólnego interfejsu z Autofac

public class BaseClass {} 

public class SubClass1 : BaseClass {} 

public class SubClass2 : BaseClass {} 

public interface IGenericInterface<T> where T : BaseClass {} 

public class SomeInstance1<T> : IGenericInterface<T> where T : SubClass1 

public class SomeInstance2<T> : IGenericInterface<T> where T : SubClass2 

Chcę wybrać SomeInstance1 lub 2 w zależności od rodzaju generycznych na podklasach.

Na przykład mam kolekcję podklas (SubClass1, 2 ....) i podczas iteracji nad nimi chcę wybrać odpowiednią klasę SomeInstance.

Odpowiedz

59

Autofac obsługuje otwarte leki generyczne. Można użyć następującego kodu jeśli rodzajowych typ jest znany w czasie kompilacji:

var builder = new ContainerBuilder(); 

builder.RegisterGeneric(typeof(SomeInstance1<>)) 
    .As(typeof(IGenericInterface<>));    

var container = builder.Build(); 

var instance1 = container.Resolve<IGenericInterface<SubClass1>>(); 

Assert.IsInstanceOfType(typeof(SomeInstance1<SubClass1>), instance1); 

Jeśli parametr typu nie jest znany aż do czasu wykonywania (co jest prawdopodobne, sprawa jeśli chcesz iterację kolekcji typów), wówczas można zbudować Twój typ za pomocą MakeGenericType:

 var typeInRuntime = typeof (SubClass1); 
     var instance1 = container.Resolve(typeof(IGenericInterface<>).MakeGenericType(typeInRuntime)); 
1

Korekta. Nie można wywołać metody MakeGenericType z kontenera. Rozwiązałem problem tworzenia instancji Generics używając "TYPE" jako parametru w wywołaniu Resolve. Budowniczy jest zarejestrowany.

 builder.RegisterGeneric(typeof (FakeRepository<>)).As(typeof (IRepository<>)).OnActivating(e => 
     { 
      var typeToLookup = e.Parameters.FirstOrDefault() as TypedParameter; 
      if (typeToLookup != null) 
      { 
       var respositoryType = typeof (FakeRepository<>); 
       Type[] typeArgs = {typeToLookup.Value.GetType()}; 
       var genericType = respositoryType.MakeGenericType(typeArgs); 
       var genericRepository = Activator.CreateInstance(genericType); 
       e.ReplaceInstance(genericRepository); 
      } 
     }); 

Następnie rozdzielczość odbywa się w ten sposób, przekazując TypedParameter do rozwiązania. W tym przypadku mam listę elementów (IItem), które są rozwiązane, że chcę utworzyć repozytorium dla wszystkich elementów tego typu.

 var items = container.Resolve<IEnumerable<IItem<string>>>(); 
     foreach (var item in items) 
     { 
      var repository = container.Resolve(typeof (IRepository<DataItemBase>), new TypedParameter(item.GetType(), item)); 
      Assert.IsNotNull(repository); 
     } 

Dzięki za post pomógł i mam nadzieję, że ta aktualizacja pomaga.

Powiązane problemy