0

使用适配器模式,结合 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 属性。Adapter 的实例应该是用外部创建的 Adaptee 实例创建的。

以下代码:

container
    .RegisterType<MyTestClass>(
        new InjectionProperty("MyTarget"));

实际上应该导致:

container
    .RegisterType<MyTestClass>(
        new InjectionProperty("MyTarget", container.Resolve<Adapter>()));

这似乎是不可能的,因为还没有 Adapter 的实例存在并且它有一个私有构造函数。

我应该使用拦截或其他东西来实现这一点吗?

4

2 回答 2

1

我很接近这个container.Resolve<Adapter>()想法,但最终的答案只是在使用InjectionProperty类配置要注入的属性时使用ResolvedParameter类:

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>();
}

我在以下帖子中找到了解决方案: Unity中的Setter / property injection without attributes

希望这对其他人有帮助。

于 2009-04-09T06:36:09.247 回答
0

那是一个Doh!片刻。

解决方法是在配置unity的时候添加如下:

.RegisterType<Target, Adapter>()

我不敢相信我错过了,这样一个解决问题的简单解决方案(我认为)。

因此,MyTestClass 上的 MyTarget 属性将解析为 Adapter 的一个实例,因为它继承自 Target。适配器显然将使用 Adaptee 类的外部创建实例来启动。

于 2009-04-02T06:09:25.303 回答