使用适配器模式,结合IoC(特别是Unity),我想创建一个对象的新实例,其属性指向适配器的属性(基本上将适配器映射到目标对象)。
作为一个例子,我有以下类结构:
public class Adaptee
{
private Adaptee() { }
public int MyProperty { get; set; }
public static Adaptee New()
{
return new Adaptee();
}
}
public class Target
{
public int MyProperty { get; set; }
}
public class Adapter : Target
{
public Adapter(Adaptee adaptee)
{
this.MyProperty = adaptee.MyProperty;
}
}
public class MyTestClass
{
public Target MyTarget { get; set; }
}
问题是Adaptee不在我的控制之下,它没有公共构造函数,因此使用了适配器。所以Adaptee创建如下
Adaptee adaptee = Adaptee.New();
adaptee.MyProperty = 5;
在实际代码中,上述代码将在外部控制的程序集中执行,然后传递给以下代码:
using (UnityContainer container = new UnityContainer())
{
container
.RegisterType<MyTestClass>(
new InjectionProperty("MyTarget"));
container.RegisterInstance<Adaptee>(adaptee, new ExternallyControlledLifetimeManager());
MyTestClass myTestClass = container.Resolve<MyTestClass>();
}
我希望代码的执行产生以下结果:
Debug.Assert(myTestClass != null);
Debug.Assert(myTestClass.MyTarget != null);
Debug.Assert(myTestClass.MyTarget.MyProperty == adaptee.MyProperty);
这意味着应该将已解析的Adapter实例注入myTestClass实例的MyTarget属性中。应该使用外部创建的Adaptee实例创建适配器实例。
以下代码:
container
.RegisterType<MyTestClass>(
new InjectionProperty("MyTarget"));
实际上应该导致这个:
container
.RegisterType<MyTestClass>(
new InjectionProperty("MyTarget", container.Resolve<Adapter>()));
这似乎不可能,因为还没有适配器实例,它有一个私有构造函数。
我应该使用拦截或其他东西来实现这个目标吗?
答案 0 :(得分:1)
我接近 container.Resolve<Adapter>()
的想法,但最后的答案只是在配置时使用 ResolvedParameter 类要使用 InjectionProperty 类注入的属性:
new InjectionProperty(
"MyTarget",
new ResolvedParameter<Adapter>()));
因此调用代码如下所示:
Adaptee adaptee = Adaptee.New();
adaptee.MyProperty = 5;
using (UnityContainer container = new UnityContainer())
{
container
.RegisterType<MyTestClass>(
new InjectionProperty(
"MyTarget",
new ResolvedParameter<Adapter>()));
container.RegisterInstance<Adaptee>(adaptee, new ExternallyControlledLifetimeManager());
MyTestClass myTestClass = container.Resolve<MyTestClass>();
}
我在以下帖子中找到了解决方案: Setter / property injection in Unity without attributes
希望这有助于其他人。
答案 1 :(得分:0)
那是一个多哈!时刻。
解决方案是在配置unity时添加以下内容:
.RegisterType<Target, Adapter>()
我无法相信我错过了这个解决问题的简单解决方案(我认为)。
因此,MyTestClass上的MyTarget属性将解析为适配器的实例,因为它继承自Target。显然,适配器将使用外部创建的Adaptee类实例启动。