Ho un'interfaccia generica che accetta due tipi generici. Voglio decorare tutte le versioni restituite, ma poiché non conosco il tipo quando si chiama EnrichWith, ovviamente non viene compilato. Ho provato a utilizzare il sovraccarico EnrichWith che passa nel contesto, pensando che forse potrei prendere i tipi generici passati e chiamare Activator.CreateInstance, ma il contesto non ha alcuna informazione utile su di esso durante il debug e l'ispezione.Decorazione di un'interfaccia generica con Structuremap
Ecco quello che ho finora. Questa è la mia interfaccia generica:
public interface IServiceOperation<in TRequest, out TResponse> where TResponse : ServiceResult, new()
{
TResponse PerformService(TRequest validatedRequest);
}
Ecco un esempio di implementazione:
public class SignUpService : IServiceOperation<SignUpRequest, SignUpResult>
{
private readonly IUserRepository _userRepo;
public SignUpService(IUserRepository userRepo)
{
_userRepo = userRepo;
}
public SignUpResult PerformService(SignUpRequest validatedRequest)
{
var user = Mapper.Map<User>(validatedRequest);
user.MarkAsLoggedIn();
user.ChangePassword(validatedRequest.UnhashedPassword);
using(var transaction = _userRepo.BeginTransaction())
{
_userRepo.Save(user);
transaction.Commit();
}
return new SignUpResult();
}
}
Ecco il mio decoratore, che prende in un altro servizio, nonché:
public class ValidateServiceDecorator<TRequest, TResponse> : IServiceOperation<TRequest, TResponse> where TResponse : ServiceResult, new()
{
private readonly IServiceOperation<TRequest, TResponse> _serviceOperation;
private readonly IValidationService _validationService;
public ValidateServiceDecorator(IServiceOperation<TRequest, TResponse> serviceOperation,
IValidationService validationService)
{
_serviceOperation = serviceOperation;
_validationService = validationService;
}
public TResponse PerformService(TRequest request)
{
var response = new TResponse();
var validationResult = _validationService.Validate(request);
if (!validationResult.IsValid)
{
response.ValidationErrors = validationResult.ValidationErrors;
return response;
}
return _serviceOperation.PerformService(request);
}
Infine, ecco come lontano ho ottenuto sul mio contenitore. Questo, ovviamente, non si compila, ma la linea EnrichWith mostra quello che sto cercando di realizzare:
public class StructureMapServiceScanner : Registry
{
public StructureMapServiceScanner()
{
Scan(scanner =>
{
scanner.AssemblyContainingType(typeof (IServiceOperation<,>));
scanner.ConnectImplementationsToTypesClosing(typeof (IServiceOperation<,>));
});
For(typeof (IServiceOperation<,>))
.EnrichWith((ioc, original) => new ValidateServiceDecorator(original, ioc.GetInstance<IValidationService>()));
}
}
E proprio perché questa domanda aveva bisogno di un po 'più di codice, ecco la mia prova che sto cercando di arrivare a passare :
Mi sento come se fosse qualcosa che dovrebbe essere semplice, e mi manca davvero qualcosa su come usare StructureMap. Potrei creare versioni specifiche per tipo per tutte le combinazioni di tipi di richiesta e risposta, ma ovviamente non è auspicabile. Quindi cosa mi sto perdendo?
È stato in grado di capirlo, utilizzando un RegistrationConvention per arricchire ogni tipo chiuso dell'interfaccia direttamente. Pubblicherei quello che ho fatto, ma non posso per altre poche ore. – Robert