6

Mam usługę, która pobiera IMyDependency w swoim konstruktorze. IMyDependency, MyDependency i usługa wszystkie żyją w tym samym zespole. MyDependency ma pojedynczy, publiczny konstruktor bez parametrów.servicestack with funq - autowiring zgodnie z konwencją

Ku mojemu zaskoczeniu, to nie działa:

container.RegisterAutoWired<IMyDependency>(); 

To rzuca "System.NullReferenceException".

To działa, jeśli mogę to zrobić:

container.RegisterAutoWiredAs<MyDependency, IMyDependency>(); 

Ale potem, tak to robi:

container.RegisterAs<MyDependency, IMyDependency>(); 

Więc jaka jest różnica? Jeśli "automatyczne okablowanie" nie może znaleźć konkretnej implementacji i nie ma znaczenia, czy usługi wymagające zależności mogą zostać rozwiązane, to co to jest automatyczne okablowanie?

Czy funkcja Funq powinna być w stanie znaleźć konkretne wdrożenia zgodnie z konwencją? Jeśli tak, to jaka jest ta konwencja, jeśli nie ta sama nazwa?

Dzięki.

Odpowiedz

4

W przypadku prostych zapytań takich jak ten najlepiej jest skontaktować się ze źródłem, np. Oto kod źródłowy RegisterAutoWired:

public IRegistration<T> RegisterAutoWired<T>() 
{ 
    var serviceFactory = GenerateAutoWireFn<T>(); 
    return this.Register(serviceFactory); 
} 

Generuje auto okablowane fabrycznie nad konkretnej implementacji. Interfejs nie ma implementacji, musi być konkretną klasą.

a kod źródłowy dla RegisterAs:

public IRegistration<TAs> RegisterAs<T, TAs>() where T : TAs 
{ 
    return this.RegisterAutoWiredAs<T, TAs>(); 
} 

który jest po prostu krótszy alias można użyć zamiast RegisterAutoWiredAs.

+0

Więc jeśli dobrze rozumiem to poprawnie, to należy robić: container.RegisterAutoWired (); Jednakże, jeśli robię tylko to, w czasie wykonywania (gdy wywołuję usługę z zależnością), otrzymuję komunikat "Wymagana zależność typu IMyDependency nie może zostać rozwiązana". Wciąż nie jestem pewien co do celu tej metody, ponieważ kontener nie wydaje się w stanie znaleźć interfejsu odpowiadającego zarejestrowanemu rodzajowi betonu. –

+3

To całkiem proste, po prostu wprowadzi to, co rejestrujesz, jeśli "Register ", niż wstrzyknie wszystkie właściwości 'MyDependency'. Jeśli chcesz wprowadzić właściwości 'IMyDependency', musisz wywołać' RegisterAs '. – mythz

+1

W moim projekcie mam ~ 200 klas według konwencji: MyClass: IMyClass. Więc zgodnie z tym za każdym razem zaimplementować nową klasę lub usunąć może zrobić okablowanie dla niego? Unity, Windsor i StructureMap mają autowire konwencji. – nerijus

8

Masz na myśli "jak mogę wdrożyć rozwiązanie do przeszukiwania złożeń i automatycznego rejestrowania klas w IOC usługi ServiceStack na podstawie konwencji?"

Jeśli tak, to mam dla Ciebie rozwiązanie:

  1. utworzyć interfejs, że zajęcia Inject-stanie będzie realizować.
  2. Zadbaj o to, aby twoje klasy, które można wstrzykiwać, zaimplementowały ten interfejs.
  3. W kodzie bootowania użyj odbicia, aby przeszukać swoje złożenia i uzyskać listę wszystkich klas implementujących interfejs wstrzykiwalny.
  4. Użyj odbicia, aby uzyskać nazwę klasy i interfejs na podstawie swoich konwencji.
  5. Zadzwoń do metody IOC usługi ServiceStack RegisterAutoWiredType i przekaż klasę i interfejs, aby je zarejestrować.

Na przykład jeśli nasza konwencja nazewnictwa jest ClassName IClassName:

private static void RegisterCustomTypes(Container container) 
{ 
    //Get the Assembly Where the injectable classes are located. 
    var assembly = Assembly.GetAssembly(typeof(IInjectable)); 

    //Get the injectable classes 
    var types =assembly.GetTypes() 
    .Where(m => m.IsClass && m.GetInterface("IInjectable") != null); 

    //loop through the injectable classes 
    foreach (var theType in types) 
    { 
    //set up the naming convention 
    var className = theType.Name; 
    var interfaceName = string.Concat("I", className); 
    //create the interface based on the naming convention 
    var theInterface = theType.GetInterface(interfaceName); 
    //register the type with the convention 
    container.RegisterAutoWiredType(theType, theInterface); 
    } 
} 

public interface IInjectable 
{ 

} 

//This class can be injected 
public interface ITestManager : IInjectable 
{ 
    void Execute(int id); 
} 

public class TestManager : ITestManager 
{ 
    public void Execute(int id) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 
+0

Od czasu mojego oryginalnego posta zrozumiałem, że Func nie ma wbudowanego wyszukiwania w poszukiwaniu. Jeśli zaimplementujesz własne odbicie zgodnie z sugestią, czy uważasz, że jakakolwiek korzyść (taka jak wydajność) pozostanie w korzystaniu z Func, z innego rozwiązania, takiego jak Ninject, itp.? –

+0

Nie jestem pewien. Może mit mit ma jakieś wskazówki na ten temat? –

+1

@Saber, DI uruchamia się tylko raz podczas uruchamiania aplikacji internetowej. Różnicę w wydajności można w tym miejscu zignorować. Windsor lub Ninject ... itd., Wszystkie są dobre. Jedynym powodem, dla którego używam Funqa nad innymi, jest to, że przychodzi z SS, jestem zbyt leniwy, aby utrzymać kolejny IoC oddzielony od pakietu SS. – Tom

Powiązane problemy