Tworzenie architektury i problemy z IOC

1

Cześć. Trafiłem na małą ścianę i chciałbym się poradzić kogoś ogarniętego w temacie IOC w Windsor Castle lub rzutowania skomplikowanych generyków.
Zacznijmy po kolei. Tworzę abstrakcję dla logiki. Logika ma klasę wejściową i klasę wyjściową i na podstawie tych dwóch klas dobiera się odpowiednią logikę do wykonania.

Interfejs klasy wychodzącej:

public interface ILogicResult

Interfejs klasy wchodzącej:

public interface ILogicIncomer<Result>
        where Result : ILogicResult

Interfejs logiki:

public interface ILogic<Incomer, Result>
        where Incomer : ILogicIncomer<Result>
        where Result : ILogicResult

No i abstrakcja dla operacji bazowych:

public abstract class Logic<Incomer, Result> : ILogic<Incomer, Result> 
        where Incomer : ILogicIncomer<Result>
        where Result : ILogicResult

Przykładowa implementacja:

public class SampleLogicResult : ILogicResult

public class SampleLogicIncomer : ILogicIncomer<SampleLogicResult>

public class SampleLogic : Logic<SampleLogicIncomer, SampleLogicResult>

Stworzyłem także handler z kontenerem Windsor Castle.

Rejestracja klas:

Container.Register(
       Classes.FromAssemblyNamed(LOGIC_PROJECT_NAME)
       .Pick()
       .WithService.AllInterfaces()
       .LifestyleTransient());

I przechwytywanie logiki:

public static async Task<Result> HandleLogicAsync<Result>(ILogicIncomer<Result> incomer)
            where Result : ILogicResult

we wnętrzu tej metody robiony jest resolve:

var logic = Container.Resolve<ILogic<ILogicIncomer<Result>, Result>>();

Problem polega na tym, że Windsor nie jest wstanie odszukać odpowiedniej implementacji.
Kontener zarejestrował takie serwisy w takiej postacji:
Przechwytywanie.PNG

Natomiast szukamy po typie: ILogic<ILogicIncomer<SampleLogicResult>, SampleLogicResult>

Nie mogłem się doszukać jak to w widnsorze ogarnąć (próbowałem rejestrowanie komponentów typu ILogic<,> ale bezskutecznie).

Tu zaczął się workaround w postaci:
(w metodzie HandleLogicAsync żeby nie było wątpliwości czym jest typ "Result")

                var incomerType = Container.Resolve<ILogicIncomer<Result>>().GetType();
                var resultType = typeof(Result);

                var logicType = typeof(ILogic<,>);

                var constructed = logicType.MakeGenericType(incomerType, resultType);

                var resolverObject = Container.Resolve(constructed);

                var logic = (ILogic<ILogicIncomer<Result>, Result>)resolverObject;

Tu problem polega na castowaniu bo dostaję błąd że 'unable to cast...' i fakt interfejs jest inny bo otrzymujemy ILogic<SampleLogicIncomer, SampleLogicResult> ale przecież SampleLogicIncomer implementuje ILogicIncomer<SampleLogicResult> więc problemy z rzutowaniem są trochę słabe..

Czy jest jakieś rozwiązanie dla Windsora? Jeżeli to zbyt ciężkie (nie znam widnsora tak dobrze jak bym chciał) to fajnie by było chociaż rozwiązać ten workaround w postaci refleksji. Z góry dzięki za pomoc. Jak wpadnę na rozwiązanie to chętnie się podzielę :)

1

Ok rozwiązałem problem.
Sam interface ILogic nie musi przyjmowac Incomera jako parametr generyczny. Wystarczy sam Result.
Zatem interface zmieniłem na:

public interface ILogic<Result>
        where Result : ILogicResult

w abstrakcji logiki zmieniłem na

public abstract class Logic<Incomer, Result> : ILogic<Result>
        where Incomer : ILogicIncomer<Result>
        where Result : ILogicResult

finał jest taki że teraz windsor na spokojnie resolvuje typ ILogic<SampleLogicResult> :

Container.Resolve<ILogic<Result>>();

1 użytkowników online, w tym zalogowanych: 0, gości: 1