Generics 开放泛型类型中的StructureMap setter注入?

Generics 开放泛型类型中的StructureMap setter注入?,generics,dependency-injection,structuremap,Generics,Dependency Injection,Structuremap,使用StructureMap,我试图在开放泛型类型上使用setter注入 我有一个抽象的泛型类: public abstract class Foo<T1, T2> : IMyInterface<T1,T2> { public ISomeDependency Bar { get; set; } } 公共抽象类Foo:IMyInterface { 公共依赖项栏{get;set;} } 我想使用Setter注入来解析Foo的任何继承者上的“Bar”。我知道我可以使用

使用StructureMap,我试图在开放泛型类型上使用setter注入

我有一个抽象的泛型类:

public abstract class Foo<T1, T2> : IMyInterface<T1,T2>
{
   public ISomeDependency Bar { get; set; }
}
公共抽象类Foo:IMyInterface
{
公共依赖项栏{get;set;}
}
我想使用Setter注入来解析Foo的任何继承者上的“Bar”。我知道我可以使用工具栏上的[SetterDependence]属性来完成这项工作,但我希望避免这样装饰我的类

我想我可以在DSL中使用ForConcreteType,如下所示:

ForConcreteType(typeof(Foo)).Configure.Setter().IsTheDefault()

但是ForConcreteType只有一个泛型实现

我已尝试在以下配置中执行此操作:

For(typeof (Foo<,>))
.Use(typeof (Foo<,>)).SetterDependency<ISomeDependency>("Bar").IsAutoFilled();
For(typeof(Foo))
.Use(typeof(Foo)).setterDependence(“Bar”).IsAutoFilled();
这将编译,但在尝试解析时引发“无法插入类型”运行时异常

有人知道在这种情况下如何完成setter注入吗?谢谢

编辑:

根据要求,以下是我试图实现的详细示例:

[Test]
public void can_resolve_open_generic_type_using_setter_injection()
{
   ObjectFactory.Initialize(x =>
                                {
x.For<ISession>().Use<DatabaseSession>();
// uncomment next line and it resolves:
// x.SetAllProperties(set => set.OfType<ISession>());
x.ForRequestedType<IHandler<OrderReceivedMessage>>()
.TheDefaultIsConcreteType<OrderHandler>();

                                });

   var instance = ObjectFactory.Container.GetInstance<IHandler<OrderReceivedMessage>>();

   instance.ShouldBeOfType<DatabaseTransactionHandler<OrderReceivedMessage>>();
   instance.ShouldBeOfType<OrderHandler>();

   var asTransactionHandler = (DatabaseTransactionHandler)instance;
   Assert.IsNotNull(asTransactionHandler.Session);

}

public interface IHandler<TMessage>
{
    void Handle(TMessage message);
}

public abstract class DatabaseTransactionHandler<TMessage> : IHandler<TMessage>
{

    // need to inject this with the default ISession
    // works when using [SetterDependency] attribute
    public ISession Session { get; set; }

    public abstract void DoHandle(TMessage message);

    public virtual void Handle(TMessage message)
    {
          using (ITransaction transaction = Session.CreateTransaction())
          {
                try
                {
                    DoHandle(message);
                    transaction.Commit();
                }
                catch (Exception handlerException)
                {
                    transaction.Rollback();
                    throw;
                }                   
          }
     }
}


public class OrderHandler : DatabaseTransactionHandler<OrderReceivedMessage>
{
    public override void DoHandle(OrderReceivedMessage message)
    {
       Order order = CreateOrderFromMessage(message);
       Session.Save(order);
    }
}
[测试]
public void可以使用setter\u injection()解析\u open\u generic\u type\u
{
ObjectFactory.Initialize(x=>
{
x、 For().Use();
//取消对下一行的注释,它将解析:
//x.SetAllProperties(set=>set.OfType());
x、 ForRequestedType()
。默认的混凝土类型();
});
var instance=ObjectFactory.Container.GetInstance();
instance.ShouldBeOfType();
instance.ShouldBeOfType();
var asTransactionHandler=(DatabaseTransactionHandler)实例;
IsNotNull(asTransactionHandler.Session);
}
公共接口IHandler
{
无效句柄(TMessage消息);
}
公共抽象类DatabaseTransactionHandler:IHandler
{
//需要使用默认的ISession注入此
//使用[SetterDependence]属性时有效
公共ISession会话{get;set;}
公共摘要void DoHandle(TMessage message);
公共虚拟无效句柄(TMessage消息)
{
使用(ITransaction transaction=Session.CreateTransaction())
{
尝试
{
DoHandle(消息);
Commit();
}
catch(异常句柄异常)
{
transaction.Rollback();
投掷;
}                   
}
}
}
公共类OrderHandler:DatabaseTransactionHandler
{
公共覆盖无效DoHandle(OrderReceivedMessage消息)
{
订单订单=CreateOrderFromMessage(消息);
会话。保存(命令);
}
}

我假设您是通过IMyInterface检索Foo,而不是通过请求Foo。因此,您需要为(typeof(IMyInterface))执行操作。 此代码适用于我(使用trunk源代码):

var容器=新容器(x=>
{
x、 For().Use();
x、 For(typeof(IMyInterface)).Use(typeof(Foo)).setterDependence(“Bar”).IsAutoFilled();
});
var instance=(Foo)container.GetInstance(typeof(IMyInterface));
WriteLine(instance.Bar.GetType().Name);
或者,您可以设置约定,以便从容器中检索到的具有ISomeDependency类型属性的任何类型都将被填充:

var container = new Container(x =>
{
    x.For<ISomeDependency>().Use<TheDependency>();
    x.For(typeof (IMyInterface<,>)).Use(typeof (Foo<,>));
    x.SetAllProperties(set => set.OfType<ISomeDependency>());
});
var容器=新容器(x=>
{
x、 For().Use();
x、 For(typeof(IMyInterface))。使用(typeof(Foo));
x、 SetAllProperties(set=>set.OfType());
});

您还可以使用x.SetAllProperties(set=>set.Matching(…)

将您的约定建立在其他条件的基础上。我假设您是通过IMyInterface检索Foo,而不是通过请求Foo。因此,您需要为(typeof(IMyInterface))执行操作。 此代码适用于我(使用trunk源代码):

var容器=新容器(x=>
{
x、 For().Use();
x、 For(typeof(IMyInterface)).Use(typeof(Foo)).setterDependence(“Bar”).IsAutoFilled();
});
var instance=(Foo)container.GetInstance(typeof(IMyInterface));
WriteLine(instance.Bar.GetType().Name);
或者,您可以设置约定,以便从容器中检索到的具有ISomeDependency类型属性的任何类型都将被填充:

var container = new Container(x =>
{
    x.For<ISomeDependency>().Use<TheDependency>();
    x.For(typeof (IMyInterface<,>)).Use(typeof (Foo<,>));
    x.SetAllProperties(set => set.OfType<ISomeDependency>());
});
var容器=新容器(x=>
{
x、 For().Use();
x、 For(typeof(IMyInterface))。使用(typeof(Foo));
x、 SetAllProperties(set=>set.OfType());
});

您还可以使用x.SetAllProperties(set=>set.Matching(…)

将您的约定建立在其他条件的基础上。实际上,我正试图通过请求Foo来检索Foo。我尝试近似ForConcreteType的功能,它将相同的具体类型传递给ForRequestedType和default.Is方法。这是因为Foo是抽象的。我实际上是在基于泛型类型解析一个具体的IFoo。如果该具体类型恰好继承自抽象基类型Foo,我希望它的Bar属性被注入默认的ISomeDependency。这是一个“开放泛型”问题。我会投票支持你的SetAllProperties解决方案。谢谢好吧,我想我不应该做假设。有时候很难遵循一个例子,所有的IFoo和IMyInterface都是虚构的名字干扰(你的评论提到了一个IFoo,而你原来的帖子没有提到)。你能发布一个完整的NUnit测试来证明你的问题吗?您可以使用组合的类和接口,只需确保包含它们的完整定义。对不起,所有的Foo内容。我同意这会使事情变得混乱。我发布了一篇编辑文章,更详细地解释了我要做的事情。正如您所看到的,IHandler是基本类型,DatabaseTransactionHandler是一个抽象类,具有Session:ISession属性。会话由DatabaseTransactionHandler的继承者用于访问数据库会话。我希望注入此属性时不使用[SetterDependence]属性或使用全局SetAllProperties方法对其进行修饰。感谢