SimpleInjector混合的生活方式,每Web请求,终身范围 [英] SimpleInjector mixed lifestyle for per web request and lifetime scope

查看:214
本文介绍了SimpleInjector混合的生活方式,每Web请求,终身范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用简单的注射器作为我IoC容器,并采用以下技术,使注册一个混合的生活方式的一些对象为每个Web请求或每个线程两种。

 接口IUnitOfWork {}
接口IWebUnitOfWork:IUnitOfWork {}
接口IThreadUnitOfWork:IUnitOfWork {}
一流的UnitOfWork:IWebUnitOfWork,IThreadUnitOfWork {}

container.RegisterPerWebRequest&所述; IWebUnitOfWork,的UnitOfWork>();
container.RegisterLifetimeScope&所述; IThreadUnitOfWork,的UnitOfWork>();
container.Register&其中; IUnitOfWork>(()=> container.GetInstance&其中;的UnitOfWork>());

//注册为混合PerWebRequest / PerLifetimeScope。
container.Register<的UnitOfWork>(()=>
{
    如果(HttpContext.Current!= NULL)
        返回container.GetInstance&其中; IWebUnitOfWork>(),为的UnitOfWork;
    其他
        返回container.GetInstance&其中; IThreadUnitOfWork>(),为的UnitOfWork;
});
 

我并不完全满意这种解决方案为每一个要求我必须定义额外的空接口,使其工作,并确保他们是由我具体的类引用。

是否有任何理由我不应该使用定义额外的接口下面的扩展方法呢?如果有一些问题,这些方法是有建立一些其他的方式,完全有信心,该容器的我目前的情况是在IIS中运行?

 公共静态无效RegisterHybridLifestyle< TService,TImplementation>(
    这种集装箱货柜)
    其中,TService:类
    其中,TImplementation:类,TService
{
    如果(System.Web.Hosting.HostingEnvironment.ApplicationHost!= NULL)
        container.RegisterPerWebRequest&所述; TService,TImplementation>();
    其他
        container.RegisterLifetimeScope&所述; TService,TImplementation>();
}

公共静态无效RegisterForLifestyle< TConcrete>(
    这种集装箱货柜)
    其中,TConcrete:类
{
    如果(HostingEnvironment.ApplicationHost!= NULL)
        container.RegisterPerWebRequest&其中; TConcrete>();
    其他
        container.RegisterLifetimeScope&其中; TConcrete>();
}
 


更新

以上问题<一href="http://stackoverflow.com/questions/14693774/when-would-you-need-simpleinjector-hybrid-registration-how-can-an-object-hoste">and这种遵循是基于SimpleInjector和混合注册的误解问题。上述和其它地方描述上的SO的技术是,当容器可以提供服务请求为网页请求和对于未的web请求的上下文中运行的后台进程。我一直在努力实现可变登记,以迎合容器的配置,是适合于Web请求的发请求。即我需要配置我的容器到IIS中工作,并在一个窗口服务工作。我不需要动态登记,可容纳既是同一时间。

这样做的结果是下面的扩展方法,我已删除从我的解决办法额外的接口: - )

 公共静态无效RegisterForScope&LT; TService,TImplementation&GT;(这个集装箱货柜)
    其中,TService:类
    其中,TImplementation:类,TService
{
    如果(System.Web.Hosting.HostingEnvironment.ApplicationHost!= NULL)
        container.RegisterPerWebRequest&所述; TService,TImplementation&GT;();
    其他
        container.RegisterLifetimeScope&所述; TService,TImplementation&GT;();
}

公共静态无效RegisterForScope&LT; TConcrete&GT;(这个集装箱货柜)
    其中,TConcrete:类
{
    如果(System.Web.Hosting.HostingEnvironment.ApplicationHost!= NULL)
        container.RegisterPerWebRequest&其中; TConcrete&GT;();
    其他
        container.RegisterLifetimeScope&其中; TConcrete&GT;();
}
 

解决方案
  

我并不完全满意这种解决方案

是的,我同意这一点。说实话,不得不做这样的事情其实很烂IMO。这就是为什么这个固定在简单的喷油器2.0。它包含生活方式的明确概念,它包含一个 Lifestyle.CreateHybrid 的方法,这使得它更容易注册的混合生活方式。

您但是,似乎并不需要一个混合的生活添加所有。混合型的生活方式是一种生活方式,可以动态切换(在每次调用的GetInstance&LT; T&GT; 和每个每次注射),而你似乎只需要在启动过程中切换。我看到使用 RegisterHybridLifestyle 扩展方法,你定义它没有伤害,但请记住,这是不是一个真正的混合生活方式(所以这个名字是有点误导)但一个简单的配置/部署交换机。

简单的喷油器2使这容易得多,而且它可以让你做这样的事情:

//定义一个曾经根据部署的生活方式。 VAR scopedLifestyle = Lifestyle.CreateHybrid(     lifestyleSelector:HostingEnvironment.ApplicationHost = NULL,     trueLifestyle:新WebRequestLifestyle()     falseLifestyle:新LifetimeScopeLifestyle()); //并将其用于登记的工作单位 //(无需额外的接口需要了)。 container.Register&LT; IUnitOfWork,的UnitOfWork&GT;(scopedLifestyle); //生活方式可以重复使用许多注册如果 //必要的。 container.RegisterManyForOpenGeneric(     的typeof(ISubscriber&其中;&1+),     typeof运算(ISubscriber&LT;&GT;)大会,     scopedLifestyle);

I am using Simple Injector as my IoC container and employ the following technique to enable registering a "mixed" lifestyle for some objects as both per web request or per thread.

interface IUnitOfWork { }
interface IWebUnitOfWork : IUnitOfWork { }
interface IThreadUnitOfWork : IUnitOfWork { }
class UnitOfWork : IWebUnitOfWork, IThreadUnitOfWork { }

container.RegisterPerWebRequest<IWebUnitOfWork, UnitOfWork>();
container.RegisterLifetimeScope<IThreadUnitOfWork, UnitOfWork>();
container.Register<IUnitOfWork>(() => container.GetInstance<UnitOfWork>());

// Register as hybrid PerWebRequest / PerLifetimeScope.
container.Register<UnitOfWork>(() =>
{
    if (HttpContext.Current != null)
        return container.GetInstance<IWebUnitOfWork>() as UnitOfWork;
    else
        return container.GetInstance<IThreadUnitOfWork>() as UnitOfWork;
});

I am not entirely satisfied with this solution as for each requirement I must define extra empty interfaces to make it work and ensure they are referenced by my concrete class.

Is there any reason I should not use the following extension methods instead of defining the extra interfaces? If there is some issue with these methods is there some other way to establish, with complete confidence, that my current instance of the container is running within IIS?

public static void RegisterHybridLifestyle<TService, TImplementation>(
    this Container container)
    where TService : class
    where TImplementation : class, TService
{
    if (System.Web.Hosting.HostingEnvironment.ApplicationHost != null)
        container.RegisterPerWebRequest<TService, TImplementation>();
    else
        container.RegisterLifetimeScope<TService, TImplementation>();
}

public static void RegisterForLifestyle<TConcrete>(
    this Container container)
    where TConcrete : class
{
    if (HostingEnvironment.ApplicationHost != null)
        container.RegisterPerWebRequest<TConcrete>();
    else
        container.RegisterLifetimeScope<TConcrete>();
}


UPDATE

The above question and this follow on question were based on a misunderstanding of SimpleInjector and hybrid registration. The techniques described above and elsewhere on SO are for when the container can be servicing request for both Web Requests and for background processes that are not running within the context of a web request. What I have been trying to achieve is variable registration to cater for a configuration of the container that is suitable for both Web Request OR Thread Request. i.e. I need to configure my container to work within IIS and to work within a windows service. I don't need the dynamic registration that can cater for both a the same time.

The outcome of this is the following extension methods and I have removed the "extra" interfaces from my solution :-)

public static void RegisterForScope<TService, TImplementation>(this Container container)
    where TService : class
    where TImplementation : class, TService
{
    if (System.Web.Hosting.HostingEnvironment.ApplicationHost != null)
        container.RegisterPerWebRequest<TService, TImplementation>();
    else
        container.RegisterLifetimeScope<TService, TImplementation>();
}

public static void RegisterForScope<TConcrete>(this Container container)
    where TConcrete : class
{
    if (System.Web.Hosting.HostingEnvironment.ApplicationHost != null)
        container.RegisterPerWebRequest<TConcrete>();
    else
        container.RegisterLifetimeScope<TConcrete>();
}

解决方案

I am not entirely satisfied with this solution

Yes, I agree with this. To be honest, having to do things like this actually sucks IMO. That's why this is fixed in Simple Injector 2.0. It contains the explicit notion of lifestyle and it will contain a Lifestyle.CreateHybrid method, that makes it much easier to register hybrid lifestyles.

You however, don't seem to need a hybrid lifestyle add all. A hybrid lifestyle is a lifestyle that can switch dynamically (on each call to GetInstance<T> and per each injection), while you only seem to need to switch during start-up. I see no harm in using the RegisterHybridLifestyle extension method as you defined it, but keep in mind that this is not really an hybrid lifestyle (so the name is a bit misleading), but simply a configuration/deployment-switch.

Simple Injector 2 makes this much easier, and it will allow you to do something like this:

// Define a lifestyle once based on the deployment.
var scopedLifestyle = Lifestyle.CreateHybrid(
    lifestyleSelector: HostingEnvironment.ApplicationHost != null,
    trueLifestyle: new WebRequestLifestyle(),
    falseLifestyle: new LifetimeScopeLifestyle());

// And use it for registering the unit of work
// (no extra interfaces needed anymore).
container.Register<IUnitOfWork, UnitOfWork>(scopedLifestyle);

// The lifestyle can be reused for many registrations if
// needed.
container.RegisterManyForOpenGeneric(
    typeof(ISubscriber<>),
    typeof(ISubscriber<>).Assembly,
    scopedLifestyle);

这篇关于SimpleInjector混合的生活方式,每Web请求,终身范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆