Generics 开放泛型类型中的StructureMap setter注入?
使用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”。我知道我可以使用
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方法对其进行修饰。感谢