与需要参数的工厂方法统一

时间:2017-04-13 11:22:57

标签: c# unity-container factory

我想在Unity容器中注册一个带有需要参数的工厂方法的类型。这些参数将通过统一解析,但仅在运行时解决。

工厂方法代码:

public static IApp Create(IOne, ITwo) {...}

注册码:

container.RegisterType(typeof(IApp), new InjectionFactory(f => App.Create(???, ???)));

我需要更换' ???' ?

更多信息:

我的Unity配置分两个阶段进行。第一阶段(应用程序正在启动),我注册了所有对象但只有一个:

container.RegisterType<IOne, One>();
container.RegisterType<ITwo, Two>();
container.RegisterType<IApp, App>();
// ...

第二阶段(用户正在记录),我juste注册了一个在我所有类的构造函数中使用的上下文对象的实例(OneTwoApp,.. 。):

var childContainer = container.CreateChildContainer();
childContainer.RegisterInstance<AppEnvironment>(new AppEnvironment(userName));

这是我不使用InjectionFactory的代码。它工作正常。现在,我必须多次注册我的IApp接口,每次都调用一个不同的静态方法。静态方法的示例:

public static IApp Create(IOne one, ITwo two, AppEnvironment env) 
{
    _one = one;
    _two = two;
    _env = env;
}

如果我注册IApp这个代码:

container.Register(typeof(IApp), new InjectionFactory(f => App.Create(container.Resolve<IOne>(), container.Resolve<ITwo>(), container.Resolve<AppEnvironment>()));

然后我的env变量没有设置。

但是如果我注册我的env实例(仅仅是为了测试目的,我不能这样做),它就可以了。

3 个答案:

答案 0 :(得分:3)

终于得到了解决方案。看起来像威利斯一样:

container.RegisterType<IApp, App>(
    new InjectionFactory(
        f => App.Create(
            f.Resolve<IOne>(), 
            f.Resolve<ITwo>()
        )
    )
);

答案 1 :(得分:2)

尝试

:%s/x\{4\}/y\{4\}/g 

答案 2 :(得分:0)

我们假设你有这个界面/类:

<ImageButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@android:drawable/ic_button"
    android:background="?attr/selectableItemBackgroundBorderless"
/>

让我们用工厂方法制作你的课程。 您不会同时使用这两个,只有一个版本:

public interface IApp { }
public class App : IApp
{
    public App(IOne iOneInstance, ITwo iTwoInstance) { /* Irrelevant */}
}

public interface IOne { }
public class OneA : IOne { }
public class OneB : IOne { }
public interface ITwo { }
public class TwoA : ITwo { }
public class TwoB : ITwo { }

如果你进行这样的注册,它应该有效:

// Version One
public class ClassWithFactoryMethodOne
{
    Func<IOne, ITwo, IApp> iAppFactory;
    public ClassWithFactoryMethodOne(Func<IOne, ITwo, IApp> iAppFactory)
    {
        this.iAppFactory = iAppFactory;
    }

    public IApp Create(IOne iOneInstance, ITwo iTwoInstance)
    {
        return this.iAppFactory(iOneInstance, iTwoInstance);
    }
}

// Version Two
public class ClassWithFactoryMethodTwo
{
    Func<string, string, IApp> iAppFactory;
    ClassWithFactoryMethodTwo(Func<string, string, IApp> iAppFactory)
    {
        this.iAppFactory = iAppFactory;
    }

    public IApp Create(string iOneNamedRegistration, string iTwoNamedRegistration)
    {
        return this.iAppFactory(iOneNamedRegistration, iTwoNamedRegistration);
    }
}

我认为,如果我解释一下我在class Program { void Main() { IUnityContainer container = new UnityContainer(); container.RegisterType<IOne, OneA>("A"); container.RegisterType<IOne, OneB>("B"); container.RegisterType<ITwo, TwoA>("A"); container.RegisterType<ITwo, TwoB>("B"); container.RegisterType<Func<IOne, ITwo, IApp>>( new InjectionFactory(c => new Func<IOne, ITwo, IApp>((iOne, iTwo) => c.Resolve<IApp>( new ParameterOverride("iOneInstance", iOne), new ParameterOverride("iTwoInstance", iTwo))))); container.RegisterType<Func<string, string, IApp>>( new InjectionFactory(c => new Func<string, string, IApp>((iOneNamedRegistration, iTwoNamedRegistration) => c.Resolve<IApp>( new ParameterOverride("iOneInstance", c.Resolve<IOne>(iOneNamedRegistration)), new ParameterOverride("iTwoInstance", c.Resolve<ITwo>(iTwoNamedRegistration)))))); // Alternate writing container.RegisterType<Func<string, string, IApp>>( new InjectionFactory(c => new Func<string, string, IApp>((iOneNamedRegistration, iTwoNamedRegistration) => { IOne iOne = c.Resolve<IOne>(iOneNamedRegistration); ITwo iTwo = c.Resolve<ITwo>(iTwoNamedRegistration); IApp iApp = c.Resolve<IApp>( new ParameterOverride("iOneInstance", iOne), new ParameterOverride("iTwoInstance", iTwo)); return iApp; }))); ClassWithFactoryMethodOne versionOne = container.Resolve<ClassWithFactoryMethodOne>(); // Somewhere you have logic and end up with instances of IOne and ITwo then you : IApp iApp1 = versionOne.Create(iOneInstance, iTwoInstance); // This doesn't compile cause you'd need the instances. ClassWithFactoryMethodTwo versionTwo = container.Resolve<ClassWithFactoryMethodTwo>(); IApp iApp2 = versionTwo.Create("A", "B"); } } 方法中写的// Alternate Writing,它会清除一些内容:

使用Main时,编写一个lambda表达式,它将接收new InjectionFactory作为参数(我将其命名为IUnityContainer。)该表达式用于创建工厂本身。在有权访问c的工厂中,我c,因此要求容器使用第一个命名注册来解析IOne工厂将收到。 ITwo也是如此。然后,我要求容器为我解析IOne iOne = c.Resolve<IOne>(iOneNamedRegistration);,使用IApp的实例覆盖名为iOneInstance的参数,并为{{1}覆盖相同的参数}。

哦,方法的最后几行就是你实际调用IOne方法的方式。第二个请求ITwo的实例创建一个CreateClassWithFactoryMethodTwo实际上是IAppIOne实际上是OneA {1}}。

还有什么不清楚的地方?