如何从Unity获取接口实例?

时间:2014-08-20 22:06:56

标签: c# unity-container

我注册了

container.RegisterType<IService, MyService>();

我想创建一个类似于

的辅助类
public class MyHelper
{
    private IService _service;

    public void SomeMethod
    {
        _service.RunSomething();
    }
}

我真的希望这个_serivce只是神奇地映射到MyService构造函数而不是null,因为我没有在其他任何地方找到IService或Service实例。

如何根据Unity映射使这个_service自我映射?

2 个答案:

答案 0 :(得分:2)

您仍然必须将注入的IService分配给您的实例。这通常通过构造函数完成:

public class MyHelper {
    private readonly IService _service;

    public MyHelper(IService service) {
        _service = service;
    }

    public void SomeMethod() {
        // _service isn't null anymore
    }
}

编辑:查看您的评论我不认为您正确使用IoC,因此我会尝试填补一些空白。您不希望创建MyHelper的新实例,无论创建它必须具有IService和任何其他依赖项MyHelper的知识。相反,您可以创建一个工厂来处理创建MyHelper的新实例,该实例也将处理其依赖项。这样,您可以设置IoC来解决此工厂的依赖关系。

public interface IInstanceFactory<out T> {
    T Create();
}

public class MyHelperFactory : IInstanceFactory<MyHelper> {
    private readonly Func<MyHelper> _myHelperFactory;

    public MyHelperFactory(Func<MyHelper> myHelperFactory) {
        _myHelperFactory = myHelperFactory;
    }

    public MyHelper Create() {
        return _myHelperFactory();
    }
}

所以我们现在有一个存储Func的工厂,用于创建MyHelper的实例。它所做的只是执行我们将在IoC设置中定义的功能。该函数所做的就是返回MyHelper的新实例。

现在我们可以设置IoC来为我们处理其他所有事情。因此,在您的IoC设置中,您可以执行以下操作(我不了解Unity,因此我将使用Autofac向您展示.Unity应该能够完成我正在展示的所有内容。)

注册服务:

container.RegisterType<MyService>().As<IService>();

注册工厂:(这是魔术发生的地方)

container.Resolve(b => {
    var service = b.Resolve<IService>();
    var myHelperFactory = new Func<MyHelper>(() => new MyHelper(service));

    return new MyHelperFactory(myHelperFactory);
}).As<IInstanceFactory<MyHelper>>();

我们在此处获得了IService的实例,我们已将其注册为MyService。然后,我们创建一个Func<MyHelper>,只创建MyHelper的新实例并传递我们刚解决的IService实例。最后,我们返回一个新的MyHelperFactory并将Func<MyHelper>传递给工厂。

所以我们假设我们有班级Foo。并且Foo需要在不了解MyHelper依赖项的情况下创建MyHelper's的实例:

public class Foo {
    private readonly IMyHelperFactory _factory;

    public Foo(IMyHelperFactory factory) {
        _factory = factory;
    }

    public void MethodThatCreatesMyHelper() {
        var instance = _factory.Create();
        // you now have a valid instance of `MyHelper`
    }
}

您要做的最后一件事就是从容器中解析Foo(只要您设置它):

var fooInstance = container.Resolve<Foo>();

fooInstance.MethodThatCreatesMyHelper();

这是我上面示例的gist。需要注意的是Foo可以在不了解其依赖关系的情况下创建实例MyHelper

答案 1 :(得分:1)

一种技术是使用构造函数中构建 MyHelper对象的对象初始化IService。这可以像lambda exssion一样简单:

public class MyHelper : IMyHelper
{
    private Func<IService> _serviceBuilderFunc;

    public MyHelper(Func<IService> serviceBuilderFunc)
    {
        _serviceBuilderFunc = serviceBuilderFunc;
    }

    public void SomeMethod()
    {
        var svc = _serviceBuilderFunc();
        svc.RunSomething();
    }
}

然后在Unity容器配置中使用RegisterType()的重载来指定构造函数参数:

var serviceBuilderFunc = () => new MyService();
container.RegisterType<IMyHelper, MyHelper>(
    new InjectionConstructor(serviceBuilderFunc));