当函数属于必须解析的类时,如何在Autofac中注册委托或函数? [英] How do I register a delegate or function with Autofac when the function belongs to a class that must be resolved?

查看:65
本文介绍了当函数属于必须解析的类时,如何在Autofac中注册委托或函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Autofac.我想将委托注入类:

I'm using Autofac. I want to inject a delegate into a class:

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 的实现来自必须从容器中解析的类,因为它具有自己的依赖性:

The implementation of ValidateAddressFunction I want to inject comes from a class that must be resolved from the container because it has dependencies of its own:

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();
    }
}

在此示例中,我使用的是委托,但我也可以注入 Func< Address,ValidationResult> .

In this example I'm using a delegate, but I could just as well be injecting Func<Address, ValidationResult>.

我可以只注入 OrderValidator ,但我宁愿不要仅使用一种方法来创建接口.如果我所有的上课需求只是一种方法,那么我宁愿直接依靠它.

I could just inject OrderValidator, but I'd rather not create an interface with just one method. If all my class needs is one method then I'd rather depend directly on that.

我如何以这样的方式注册委托或 Func ,以便在解决该问题时,将解析包含该方法的类,然后可以从已解决的实例中使用该方法?/p>

How do I register the delegate or Func in such a way that when it's resolved, the class that contains the method will be resolved, and then I can use the method from the resolved instance?

推荐答案

使用可解析提供该方法的类型的工厂方法注册委托或 Func< Address,ValidationResult> 方法.

Register the delegate or Func<Address, ValidationResult> using a factory method that resolves the type which provides the method, and then returns the method.

在您的示例中,您将要解析 OrderValidator 并返回其 ValidateAddress 方法.

In your example you would want to resolve OrderValidator and return its ValidateAddress method.

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> 而不是委托,则此方法将完全相同:

This would work exactly the same way if you were registering Func<Address, ValidationResult> instead of a delegate:

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

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

You can simplify the registration using an extension. It's not that much shorter, but it still helps if you're likely to have multiple such registrations. It might also help to express your intent so it's perfectly clear that you're registering a delegate to be injected as opposed to a class instance or interface implementation.

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注册是临时的,因此提供委托的类的生存期由该类的注册确定.

Autofac registrations are transient by default, so the lifetime of the class that provides the delegate is determined by the registration of that class.

现在注册看起来像这样:

Now the registration would look like this:

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

或者,如果提供方法的依赖项(在本例中为 OrderValidator )注册了一个名称,我们必须使用该名称来解决它:

Or, if the dependency which provides the method - in this case OrderValidator is registered with a name and we must resolve it using that name:

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

这篇关于当函数属于必须解析的类时,如何在Autofac中注册委托或函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆