使用Func和依赖注入的Autofac动态调用

时间:2014-07-21 23:01:57

标签: c# dependency-injection autofac service-locator

假设我有一个课程如下

public class Foo
{
    public Foo(string someTitle, IFooService fooService)
    { 
        // do stuff
    }
}

我知道我可以使用DI和autofac

来实例化它
public class Bar
{
    public Bar(Func < string, IFooService, Foo > foo, IFooService fooService)
    {
        var foo = foo("some string", fooService);
    }
}

但我想知道Bar是否有任何方法可以不了解IFooService的任何内容?我不想为了满足func而将IFooService注入Bar。

基本上是这样的

// pseudo code - don't use
public class Bar
{
    public Bar(Func < string, Foo > foo)
    {
        var foo = foo("some string");
    }
}

我在我的应用中真正想做的是删除所有服务位置实例,并完全依赖依赖注入。

2 个答案:

答案 0 :(得分:5)

Autofac应该能够使用the Func<T> implicit relationship完全按照您的意愿完成。

这是一个小型repro,显示如何省略IFooService中的Func<T>参数,只要其他依赖项可以通过Autofac解决,您就可以了。< / p>

做一些疯狂工作的样本类型......

public class Bar
{
    private Foo _foo;

    // This constructor looks like what you're aiming for...
    public Bar(Func<string, Foo> factory)
    {
        this._foo = factory("title");
    }

    public void ShowMeCoolStuff()
    {
        this._foo.DoWork();
    }
}

public class Foo
{
    private string _title;
    private IFooService _service;

    // The Foo class takes the title AND an IFooService...
    public Foo(string title, IFooService service)
    {
        this._title = title;
        this._service = service;
    }

    public void DoWork()
    {
        Console.WriteLine("Foo title = {0}", this._title);
        this._service.DoMoreWork();
    }
}

public interface IFooService
{
    void DoMoreWork();
}

public class FooService : IFooService
{
    public void DoMoreWork()
    {
        Console.WriteLine("FooService doing more work.");
    }
}

注册时,请确保所有依赖项都已注册 - FooBar,正在实施IFooService

var builder = new ContainerBuilder();
builder.RegisterType<Foo>();
builder.RegisterType<Bar>();
builder.RegisterType<FooService>().As<IFooService>();
var container = builder.Build();

当你解决时,一切都紧紧抓住了。这个决议......

var bar = container.Resolve<Bar>();
bar.ShowMeCoolStuff();

...将产生以下控制台输出:

Foo title = title
FooService doing more work.

There is fairly robust documentation with examples over on the Autofac site.

答案 1 :(得分:2)

您使用工厂的地方:

public interface IFooFactory
{
    Foo CreateFoo(string value);
}

栏可以简单地依赖IFooFactory

实施可以如下所示:

public class FooFactory : IFooFactory
{
    private readonly IFooService fooService;

    public FooFactory(IFooService fooService)
    { 
        this.fooService = fooService;
    }

    public Foo CreateFoo(string value)
    {
        return new Foo(value, this.fooService);
    }
}

但是给定的字符串看起来像是运行时值,即从请求到请求或从调用到调用的值。根据解释hereherehere,防止将运行时值与设计时依赖性混合在一起。而是将运行时值作为方法参数传递给您调用的Foo方法。这将彻底解决问题。