解析没有公共构造函数的外部创建的对象实例

时间:2009-04-01 05:41:52

标签: inversion-of-control unity-container

使用适配器模式,结合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>()));

这似乎不可能,因为还没有适配器实例,它有一个私有构造函数。

我应该使用拦截或其他东西来实现这个目标吗?

2 个答案:

答案 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类实例启动。