工厂方法只调用一次

时间:2016-05-06 04:55:12

标签: unity-container constructor-injection

以下是我的注册码

container.RegisterType<IFoo, Foo>(
                    new InjectionConstructor(typeof (IEnumerable<int>),
                        new ResolvedParameter<IBar1>,
                        new InjectionParameter<IBar2>(CreateBar2(container)))

问题是CreateBar2(container)只在程序启动时调用一次,我需要在每次调用IFoo时调用它

另一个问题,哪一个是最佳实践

container.RegisterType<IFoo, Foo>(
                    new InjectionConstructor(typeof (IEnumerable<int>),
                        new ResolvedParameter<IBar1>,
                        new InjectionParameter<IBar2>(CreateBar2(container)))

container.RegisterType<IFoo, Foo>(
                    new InjectionConstructor(typeof (IEnumerable<int>),
                        new ResolvedParameter<IBar1>,
                        CreateBar2(container))

1 个答案:

答案 0 :(得分:1)

首先,您需要使用其他LifetimeManagerTransientLifetimeManager每次都会解析一个新实例。

    container.RegisterType<IFoo, Foo>(
                        new InjectionConstructor(typeof (IEnumerable<int>),
                            new ResolvedParameter<IBar1>,
                            new InjectionParameter<IBar2>(CreateBar2(container)), 
                            new TransientLifetimeManager())

这意味着每次注入或解析IFoo时,它都会每次调用构造函数。但是,您似乎正在注入一个方法,该方法将在注册时执行 - CreateBar2(container)。这和写作一样:

var bar2 = CreateBar2(container); // Called once.
container.RegisterType<IFoo, Foo>(
                    new InjectionConstructor(typeof (IEnumerable<int>),
                        new ResolvedParameter<IBar1>,
                        new InjectionParameter<IBar2>(bar2))

我建议你把它抽象给一个类而不是注入它。这样你也可以控制对它的调用。

public interface ICreateBar2
{
    IBar CreateBar2();
}

public class CreateBar2
{
    private IUnityContainer _container;

    public CreateBar(IUnityContainer container)
    {
        _container = container;
    }

    public IBar CreateBar2()
    {
        // Do stuff.
        return CreateBar2(_container); // Or what you need to do?
    }
}

并将注册更改为

container.RegisterType<IFoo, Foo>(
                    new InjectionConstructor(typeof (IEnumerable<int>),
                        new ResolvedParameter<IBar1>,
                        new ResolvedParameter<ICreateBar2>),
                        new TransientLifetimeManager())

container.RegisterType<ICreateBar2, CreateBar2>(new TransientLifetimeManager());

或者可能RegisterInstance,如果它更适合您的需求?

请务必将IFoo的构造函数更改为接受ICreateBar。使用此方法的最佳方法是您不再需要InjectionConstructor,因为所有参数都可以通过Unity解决。

container.RegisterType<IFoo, Foo>(new TransientLifetimeManager());

如果你真的需要在当前范围内保留CreateBar2() - 方法,你可以注入一个Func,它实际上返回与CreateBar2()相同的值。

我不知道CreateBar()的完整签名,但您可以这样做:

container.RegisterType<IFoo, Foo>(
                    new InjectionConstructor(typeof (IEnumerable<int>),
                        new ResolvedParameter<IBar1>,
                        new InjectionParameter<Func<IBar2>>(
                            new Func<IBar2>(()=> CreateBar2(container)));

但现在您需要将Func<IBar2>注入IFoo构造函数。这将导致它在构造函数中使用它时执行。

public class Foo : IFoo
{
    IBar1 _bar1;
    IBar2 _bar2;

    public Bar(IBar1 bar1, Func<IBar2> bar2Func)
    {
        _bar1 = bar1;
        _bar2 = bar2Func();
    }
}