gpt4 book ai didi

c# - 当函数属于必须解析的类时,如何向 Autofac 注册委托(delegate)或函数?

转载 作者:行者123 更新时间:2023-12-05 01:40:31 25 4
gpt4 key购买 nike

我正在使用 Autofac。我想将一个委托(delegate)注入(inject)一个类:

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方法。

var builder = new ContainerBuilder();

// register the class that provides the method and its dependencies.

builder.RegisterType<OrderValidator>();
builder.RegisterType<SomeDependency>().As<ISomeDependency>();

// register the delegate using a factory method that resolves
// the type that provides the method and then returns the method.

builder.Register<ValidateAddressFunction>(context =>
{
var validator = context.Resolve<OrderValidator>();
return validator.ValidateAddress;
});

如果您注册 Func<Address, ValidationResult>,这将以完全相同的方式工作而不是代表:

builder.Register<Func<Address, ValidationResult>>(context =>
{
var validator = context.Resolve<OrderValidator>();
return validator.ValidateAddress;
});

您可以使用扩展程序简化注册。它并没有那么短,但如果您可能有多个这样的注册,它仍然有帮助。它也可能有助于表达您的意图,因此很明显您正在注册要注入(inject)的委托(delegate),而不是类实例或接口(interface)实现。

public static class AutofacDelegateExtensions
{
public static IRegistrationBuilder<TDelegate, SimpleActivatorData, SingleRegistrationStyle> RegisterDelegateFromService<TService, TDelegate>(
this ContainerBuilder builder,
Func<TService, TDelegate> getDelegateFromService,
string sourceComponentName = null)
where TDelegate : class
{
var registrationFunction = new Func<IComponentContext, TDelegate>(context =>
{
var source = sourceComponentName == null
? context.Resolve<TService>()
: context.ResolveNamed<TService>(sourceComponentName);
return getDelegateFromService(source);
});

return builder.Register(registrationFunction);
}
}

默认情况下,Autofac 注册是暂时的,因此提供委托(delegate)的类的生命周期由该类的注册决定。

现在注册看起来像这样:

builder.RegisterDelegateFromService<OrderValidator, ValidateAddressFunction>(validator =>
validator.ValidateAddress);

或者,如果提供方法的依赖项 - 在本例中为 OrderValidator已注册名称,我们必须使用该名称解析它:

builder.RegisterDelegateFromService<OrderValidator, ValidateAddressFunction>(validator =>
validator.ValidateAddress, "RegistrationName");

关于c# - 当函数属于必须解析的类时,如何向 Autofac 注册委托(delegate)或函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56480518/

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