工厂方法只调用一次

Factory method only called once

以下是我的注册码

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))

首先,你需要使用不同的LifetimeManager. TransientLifetimeManager每次都会解析一个新的实例。

    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))

我建议您将其抽象为 class 并注入。这样你也可以控制对它的调用。

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,它实际上 returns 与 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();
    }
}