Unity 与需要参数的工厂方法
Unity with factory method who need parameters
我想用需要参数的工厂方法在 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>();
// ...
第二阶段(用户正在登录),我只是注册了一个上下文对象的实例,该对象在我所有 类(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 实例(只是为了测试目的,我不能这样做),它会起作用。
尝试
container.RegisterType(
typeof(IApp),
new InjectionFactory(f => App.Create(
container.Resolve<IOne>(),
container.Resolve<ITwo>())));
假设你有这个 Interface/Class :
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 { }
让我们用工厂方法把它变成你的 class。 你不会同时使用这两个,只使用一个版本:
// 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");
}
}
我想如果我解释一下我在Main
方法中写的// Alternate Writing
,它会澄清一些事情:
当您使用 new InjectionFactory
时,您编写了一个 lambda 表达式,它将接收一个 IUnityContainer
作为参数(我将其命名为 c
。)该表达式用于创建工厂本身.在可以访问 c
的工厂中,我然后 IOne iOne = c.Resolve<IOne>(iOneNamedRegistration);
,因此要求 容器 解析 IOne,使用第一个 named工厂将收到的注册。 ITwo 也是如此。然后,我要求 容器 为我解析一个 IApp
,用 IOne
的实例覆盖名为 iOneInstance
的参数,ITwo
.
哦,该方法的最后几行就是您实际调用 Create
方法的方式。第二个会要求 ClassWithFactoryMethodTwo
的实例创建一个 IApp
,其中 IOne
实际上是 OneA
,而 ITwo
实际上是 TwoB
.
还有什么不清楚的吗?
终于找到解决办法了。看起来像 willys one :
container.RegisterType<IApp, App>(
new InjectionFactory(
f => App.Create(
f.Resolve<IOne>(),
f.Resolve<ITwo>()
)
)
);
我想用需要参数的工厂方法在 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>();
// ...
第二阶段(用户正在登录),我只是注册了一个上下文对象的实例,该对象在我所有 类(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 实例(只是为了测试目的,我不能这样做),它会起作用。
尝试
container.RegisterType(
typeof(IApp),
new InjectionFactory(f => App.Create(
container.Resolve<IOne>(),
container.Resolve<ITwo>())));
假设你有这个 Interface/Class :
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 { }
让我们用工厂方法把它变成你的 class。 你不会同时使用这两个,只使用一个版本:
// 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");
}
}
我想如果我解释一下我在Main
方法中写的// Alternate Writing
,它会澄清一些事情:
当您使用 new InjectionFactory
时,您编写了一个 lambda 表达式,它将接收一个 IUnityContainer
作为参数(我将其命名为 c
。)该表达式用于创建工厂本身.在可以访问 c
的工厂中,我然后 IOne iOne = c.Resolve<IOne>(iOneNamedRegistration);
,因此要求 容器 解析 IOne,使用第一个 named工厂将收到的注册。 ITwo 也是如此。然后,我要求 容器 为我解析一个 IApp
,用 IOne
的实例覆盖名为 iOneInstance
的参数,ITwo
.
哦,该方法的最后几行就是您实际调用 Create
方法的方式。第二个会要求 ClassWithFactoryMethodTwo
的实例创建一个 IApp
,其中 IOne
实际上是 OneA
,而 ITwo
实际上是 TwoB
.
还有什么不清楚的吗?
终于找到解决办法了。看起来像 willys one :
container.RegisterType<IApp, App>(
new InjectionFactory(
f => App.Create(
f.Resolve<IOne>(),
f.Resolve<ITwo>()
)
)
);