简体   繁体   中英

resolving instance of class inside of method using autofac

Using this PipelineX class below, is there any way to resolve the filters applied to the pipline without injecting the autofac container and calling _container.Resolve();

 public class PipelineX<T> : FilterBase<T>, IPipelineX<T>
{
    private readonly IContainer _container;

    public PipelineX(IContainer container)
    {
        _container = container;
    }
    protected override T Process(T input)
    {
        return input;
    }

    public PipelineX<T> FilterBy<X>()
    {
        var filter = _container.Resolve(typeof(X)) as IFilter<T>;
        Register(filter);
        return this;
    }                             
}

To avoid the usage of Autofac as a service locator you can register your own factory method into it, in this case:

builder.Register<Func<Type, object>>((c, p) =>
{
    var context = c.Resolve<IComponentContext>();
    return type => context.Resolve(type);
});

and use that in your PipelineX class like this:

private readonly Func<Type, object> filterFactory;

public PipelineX(Func<Type, object> filterFactory)
{
    this.filterFactory = filterFactory;
}

protected override T Process(T input)
{
    return input;
}

public PipelineX<T> FilterBy<X>()
{
    var filter = this.filterFactory(typeof(X)) as IFilter<T>;
    Register(filter);
    return this;
}

Consider: This only removes the hard reference to the Autofac container, it's still using an abstract object factory which is not self explanatory enough and should be replaced by a custom filter factory or selector implementation.

This is similar to Péter's answer but uses a custom factory:

public class FilterFactory
{
    private readonly Func<Type, object> _factoryFunc;

    public FilterFactory(Func<Type, object> factoryFunc)
    {
        _factoryFunc = factoryFunc ?? throw new ArgumentNullException(nameof(factoryFunc));
    }

    public IFilter<T> Create<X, T>() 
    {
        IFilter<T> filter = Create<T>(typeof(X));

        return filter;
    }

    public IFilter<T> Create<T>(Type type) 
    {
        var filter = _factoryFunc(type) as IFilter<T>;

        if (filter == null)
        {
            throw new ArgumentException($"Could not find filter for type '{type.FullName}'");
        }

        return filter;
    }
}

PipelineX implementation would be:

public class PipelineX<T> : FilterBase<T>, IPipelineX<T>
{
    private readonly FilterFactory _factory;

    public PipelineX(FilterFactory factory)
    {
        _factory = factory;
    }

    protected override T Process(T input)
    {
        return input;
    }

    public PipelineX<T> FilterBy<X>()
    {
        var filter = _factory.Create<X,T>() as IFilter<T>;
        Register(filter);
        return this;
    }
}

Registering the factory using Autofac:

builder.Register<FilterFactory>(c =>
{
    var context = c.Resolve<IComponentContext>();
    return new FilterFactory(context.Resolve);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM