2013-04-16 12 views
5

Mam ogólnego interfejsu IRepository<T> i dwie implementacje xrmRepository<T> i efRepository<T>Ninject kontekstu Oprawa w/Otwórz Generics

Chcę zmienić wiązanie na podstawie T dokładniej używać xrmRepository gdy T wywodzi Entity. Jak mogę to zrobić?

Obecnie mam:

kernel.Bind(typeof(IRepository<>)).To(typeof(efRepository<>)).InRequestScope(); 
kernel.Bind(typeof(IRepository<>)).To(typeof(xrmRepository<>)).When(request => request.Service.GetGenericArguments()[0].GetType().IsSubclassOf(typeof(Entity))).InRequestScope(); 

Ale gdy próbuję rozwiązać IRepository<Contact> idzie do efRepository, choć Kontakt dziedziczy podmiotu.

Nie chcę używać nazwanych wiązań, w przeciwnym razie będę musiał dodawać nazwy wszędzie.

Odpowiedz

2

Można również zdefiniować powiązania w ten sposób. Nie wiem o wydajności w czasie wykonywania, ale myślę, że jest bardziej czytelna w ten sposób. A jeśli czegoś nie przeoczę, powinno to spowodować takie samo zachowanie.

kernel.Bind(typeof(IRepository<>)) 
     .To(typeof(efRepository<>)) 
     .InRequestScope(); 

kernel.Bind<IRepository<Entity>>() 
     .To<xrmRepository<Entity>>() 
     .InRequestScope(); 

Edit

Jeśli celem jest wykorzystanie xrmRepository dla każdej klasy dziedziczy od Podmiotu to powinno załatwić sprawę

kernel.Bind(typeof(IRepository<>)) 
        .To(typeof(XrmRepository<>)) 
        .When(request => typeof(Entity).IsAssignableFrom(request.Service.GetGenericArguments()[0])); 
+0

Nie działa z wykorzystaniem klasy bazowej "Jednostka". Nadal wiążę się z efRepository. Działa, jeśli używa samej klasy (np. Kontakt). –

+0

Czy chcesz rozwiązać IRepository dla xrmRepository dla wszystkich podklas Entity? – treze

+0

Tak! Ale prawdopodobnie utworzę IXRMRepository: IRepository, ponieważ nie mogę go uruchomić. –

1

Użyj metody When, aby zadeklarować warunek wiązania. Przykład podano poniżej:

kernel.Bind(typeof(IRepository<>)) 
     .To(typeof(efRepository<>)) 
     .When(request => request.Service.GetGenericArguments()[0] == typeof(Entity)) 
     .InRequestScope(); 

kernel.Bind(typeof(IRepository<>)) 
     .To(typeof(xrmRepository<>)) 
     .InRequestScope(); 

kernel.Get<IRepository<Entity>>(); //will return efRepository<Entity> 

kernel.Get<IRepository<int>>(); //will return xrmRepository<int> 
+0

Wciąż dostaję błąd „GenericArguments [0],„sf2015 .Infrastructure.Xrm.Contact ', w' sf2015.Repositories.sfRepository'1 [T] 'narusza ograniczenie typu parametru' T '. ". Informacje dodatkowe: f2015.Infrastructure.Xrm.Contact jest typu Microsoft.Xrm.Sdk.Entity. Musiałem zmienić First() na [0], a xrmRepository to ten, który powinien wiązać się z Entity. Zobacz zaktualizowane pytanie. –

+0

@JoaoLeme podaje definicje interfejsów i ich implementację. Podaj przykłady wywołania ** Uzyskaj ** i oczekiwane wyniki –

+0

Podczas wywoływania Uzyskaj z nowego modułu działa, jeśli używam ... GetGenericArguments(). First() == typeof (Kontakt) ... i wywołaj jądro. >(); ale jeśli zastąpię Contact na powiązanie przez jego odziedziczone Entity klasy i wywołanie jądra.Zamów >() Otrzymuję ten sam błąd. Nawiasem mówiąc, robienie tego samego triku rozwiązywania problemów (zastępowanie Entity by Contact) w RegisterServices w NinjectWebCommon nie działa (Eitherway daje mi ten sam błąd). –