有没有办法为特定的生活方式定义范围?我试图实现我想要在应用程序中持久化的我自己的作用域,但在内部我也创建了另一个作用域,然后请求GetInstance返回内部作用域实例。
我想如果我可以将我的生活方式定义为:
public class MyScopedLifestyle : ExecutionContextScopeLifestyle
{
public MyScopedLifestyle(bool disposeInstanceWhenScopeEnds)
: base("MyScopedLifestyle", disposeInstanceWhenScopeEnds)
{
}
protected override int Length
{
get
{
return 100;
}
}
}
我的用法是:
var container = new Container();
container.Register<IRequestData, RequestData>(new MyScopedLifestyle());
// i had hoped I could say
// container.BeginExecutionContextScope(MyScopedLifestyle)
// or something similar
// this is controlled by me
using (var scope1 = container.BeginExecutionContextScope())
{
// do some stuff
container.GetInstance<IRequestData>().RequestMarket = "en-US";
// this is done via the webapi execution scope (using simpleinjector dependency resolver)
using (var scope2 = container.BeginExecutionContextScope())
{
Assert.Equal("en-US", container.GetInstance<IRequestData>().RequestMarket); // false
}
}
但我不确定如何在创建内部执行范围时利用我的自定义生活方式。
我真正想要发生的是,我在scope1中使用的IRequestData实例与scope2中的IRequestData实例相同。这是我用SimpleInjector可以实现的吗?
修改 我删除了这样一个事实,即我尝试按OWIN请求创建对象实例,而不是每个WebAPI请求。理想情况下,我试图创建:
container.RegisterOwinRequest<IRequestData, RequestData>();
因此,当我在管道中的任何地方解析IFoo
时(无论是OWIN中间件,还是WebAPI部分,都会针对特定请求返回相同的实例)。
编辑2 为了更好的名字,我们改变了我们的IFoo / Foo / MyProperty。
答案 0 :(得分:2)
您尝试使用自定义生活方式完成的任务绝对可能,但可能并不那么容易,因为您必须将该范围存储在某处(可能在CallContext
中)并且需要创建一个{ {1}}方法,用于创建新范围并具有自定义BeginMyCustomScope
实现,该实现在调用Scope
时将自己从CallContext
中删除。我认为这是太多的工作和太多的复杂性。
存在问题是因为在您想要设置Dispose
属性期间,没有启动Web API请求范围。通常强制启动此范围的方法是在RequestMarket
上调用GetDependencyScope
方法:
HttpRequestMessage
在此之后,您可以解析message.GetDependencyScope();
并按预期工作:
IRequestData
但是我不确定container.GetInstance<IRequestData>().RequestMarket = "en-US";
是否在那个时间点可用,所以如果没有,我认为在评论中表达的HttpRequestMessage
是一个很好的选择。< / p>
过去,在callstack之间传递数据的好方法是使用特定于线程的变量,但是当使用async / await模型时,与Web API和OWIN一样,这显然会失败。因此,执行此操作的新方法是使用DelegatingHandler
。因此,您可以执行以下操作,而不是使用CallContext
:
DelegatingHandler
当OWIN请求开始时,你这样做:
container.RegisterInitializer<IRequestData>(data =>
data.RequestMarket = (string)CallContext.LogicalGetData("RequestMarketKey"));