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:
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ę :)
- Przechwytywanie.PNG (3 KB) - ściągnięć: 84