gpt4 book ai didi

c# - 用 Structuremap 装饰通用接口(interface)

转载 作者:太空狗 更新时间:2023-10-29 23:02:13 24 4
gpt4 key购买 nike

我有一个通用接口(interface),它接受两个通用类型。我想装饰所有返回的版本,但由于我在调用 EnrichWith 时不知道类型,因此显然无法编译。我尝试使用在上下文中传递的 EnrichWith 重载,想也许我可以获取传入的泛型类型并调用 Activator.CreateInstance,但是在调试和检查上下文时上下文没有任何有用的信息。

这是我目前所拥有的。这是我的通用界面:

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 的东西。我可以为请求和响应类型的所有组合创建类型特定的版本,但显然这是不可取的。那我错过了什么?

最佳答案

最终能够弄清楚。我创建了一个 RegistrationConvention:

public class ServiceRegistrationConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
var interfacesImplemented = type.GetInterfaces();

foreach (var interfaceImplemented in interfacesImplemented)
{
if (interfaceImplemented.IsGenericType && interfaceImplemented.GetGenericTypeDefinition() == typeof(IServiceOperation<,>))
{
var genericParameters = interfaceImplemented.GetGenericArguments();
var closedValidatorType = typeof(ValidateServiceDecorator<,>).MakeGenericType(genericParameters);

registry.For(interfaceImplemented)
.EnrichWith((context, original) => Activator.CreateInstance(closedValidatorType, original,
context.GetInstance<IValidationService>()));
}
}
}
}

关于c# - 用 Structuremap 装饰通用接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7954988/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com