我想在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注册了一个在我所有类的构造函数中使用的上下文对象的实例(One
,Two
,App
,.. 。):
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实例(仅仅是为了测试目的,我不能这样做),它就可以了。
答案 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
的实例创建一个Create
,ClassWithFactoryMethodTwo
实际上是IApp
,IOne
实际上是OneA
{1}}。
还有什么不清楚的地方?