我正在使用来自 Microsoft.Extensions.DependencyInjection 的 IServiceCollection/IServiceProvider。
我想向类中注入(inject)一个委托(delegate):
public delegate ValidationResult ValidateAddressFunction(Address address);
public class OrderSubmitHandler
{
private readonly ValidateAddressFunction _validateAddress;
public OrderSubmitHandler(ValidateAddressFunction validateAddress)
{
_validateAddress = validateAddress;
}
public void SubmitOrder(Order order)
{
var addressValidation = _validateAddress(order.ShippingAddress);
if(!addressValidation.IsValid)
throw new Exception("Your address is invalid!");
}
}
执行ValidateAddressFunction
我想注入(inject)来自一个必须从容器中解析的类,因为它有自己的依赖关系:
public class OrderValidator
{
private readonly ISomeDependency _dependency;
public OrderValidator(ISomeDependency dependency)
{
_dependency = dependency;
}
public ValidationResult ValidateAddress(Address address)
{
// use _dependency
// validate the order
// return a result
return new ValidationResult();
}
}
在这个例子中,我使用了一个委托(delegate),但我也可以注入(inject) Func<Address, ValidationResult>
.
我可以注入(inject) OrderValidator
,但我不想只用一种方法创建接口(interface)。如果我的类(class)只需要一种方法,那么我宁愿直接依赖它。
如何注册委托(delegate)或 Func
以这样一种方式,当它被解析时,包含该方法的类将被解析,然后我可以使用已解析实例中的方法?
最佳答案
注册代表或Func<Address, ValidationResult>
使用解析提供该方法的类型的工厂方法,然后返回该方法。
在您的示例中,您可能希望解析 OrderValidator
并返回其 ValidateAddress
方法。
// register the class that provides the method and its dependencies.
services.AddSingleton<OrderValidator>();
services.AddSingleton<ISomeDependency, SomeDependency>();
// register the delegate using a factory method that resolves
// the type that provides the method and then returns the method.
services.AddSingleton<ValidateAddressFunction>(serviceProvider =>
{
var validator = serviceProvider.GetRequiredService<OrderValidator>();
return validator.ValidateAddress;
});
如果您注册 Func<Address, ValidationResult>
,这将以完全相同的方式工作而不是代表:
services.AddSingleton<Func<Address,ValidationResult>>(serviceProvider =>
{
var validator = serviceProvider.GetRequiredService<OrderValidator>();
return validator.ValidateAddress;
});
您可以使用扩展程序简化注册。它并没有那么短,但如果您可能有多个这样的注册,它仍然有帮助。它也可能有助于表达您的意图,因此很明显您正在注册要注入(inject)的委托(delegate)而不是类实例或接口(interface)实现:
public static class ServiceCollectionDelegateExtensions
{
public static IServiceCollection RegisterDelegateFromService<TService, TDelegate>(
this IServiceCollection serviceCollection,
Func<TService, TDelegate> getDelegateFromService)
where TDelegate : Delegate
{
return serviceCollection.AddTransient(serviceProvider =>
getDelegateFromService(serviceProvider.GetRequiredService<TService>()));
}
}
在这种情况下,代理是使用 AddTransient
注册的因为类的生命周期是在类注册时真正确定的。
现在注册看起来像这样:
services.RegisterDelegateFromService<OrderValidator, ValidateAddressFunction>
(validator => validator.ValidateAddress);
关于c# - 当函数属于必须解析的类时,如何向 IServiceCollection 注册委托(delegate)或函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56447219/