私はジェネリックインターフェースを持っています。これには2つのジェネリックタイプがあります。返されるすべてのバージョンを飾りたいですが、EnrichWithを呼び出すときに型がわからないので、明らかにコンパイルされません。私はコンテキストで渡すEnrichWithオーバーロードを使用しようとしましたが、渡されたジェネリック型を取得してActivator.CreateInstanceを呼び出せるかもしれないと思っていましたが、デバッグや検査の際にコンテキストに役立つ情報はありません。Structuremapで汎用インターフェースをデコレートする
これまで私がこれまで持っていたことは次のとおりです。これは私の一般的なインタフェースです:
public interface IServiceOperation<in TRequest, out TResponse> where TResponse : ServiceResult, new()
{
TResponse PerformService(TRequest validatedRequest);
}
は、ここでサンプル実装です:ここで
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();
}
}
は、同様に別のサービスになります私のデコレータ、次のとおりです。
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);
}
最後に、ここではどのようにあります私はコンテナに手を差し伸べました。これは明らかにコンパイルされませんが、EnrichWithラインは、私が達成しようとしているものを示しています
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>()));
}
}
そして、この質問には、もう少しコードが必要という理由だけで、ここで私が合格するために取得しようとしている私のテストです:
[TestClass]
public class StructureMapServiceScannerSpecs
{
[TestMethod]
public void Test()
{
ObjectFactory.Configure(cfg =>
{
cfg.AddRegistry<StructureMapServiceScanner>();
cfg.For<IUserRepository>().Use(new Mock<IUserRepository>().Object);
cfg.For<IValidationService>().Use(new Mock<IValidationService>().Object);
});
var service = ObjectFactory.GetInstance<IServiceOperation<SignUpRequest, SignUpResult>>();
service.ShouldNotBeNull();
service.ShouldBeType<ValidateServiceDecorator<SignUpRequest, SignUpResult>>();
}
}
私はこれがシンプルでなければならないと感じ、私は本当にStructureMapの使い方に何か不足しています。私は、Request型とResponse型のすべての組み合わせに対して型固有のバージョンを作成できますが、それは望ましくないことは明らかです。それで私は何が欠けているのですか?
RegistrationConventionを使用して、インターフェイスの各閉じたタイプを直接充実させることができました。私がしたことを投稿したいが、数時間はできない。 – Robert