其他分享
首页 > 其他分享> > 结合WCF和“常规”注册的SimpleInjector

结合WCF和“常规”注册的SimpleInjector

作者:互联网

我正在开发Windows服务,它将承载两件事:

> WCF服务
>定期执行作业的“常规” Windows服务(使用Quartz.net)

因此,基本上,一个应用程序(可执行)承载这两种服务类型.

这两种服务类型都需要使用存储库和其他注入的依赖项.我正在使用SimpleInjector.

我已经使用SimpleInjectors WCF扩展来启动并运行WCF部分:

public class DependencyResolver : IPackage
{
    public void RegisterServices(Container container)
    {
        container.EnablePerWcfOperationLifestyle();
        var wcfLifestyle = new WcfOperationLifestyle();

        container.Register<IUnitOfWork, UnitOfWork>(wcfLifestyle);
        container.Register<ICustomerRepository, CustomerRepository>(wcfLifestyle);
        //etc...

        container.RegisterWcfServices(Assembly.GetExecutingAssembly());
    }
}

我的问题:我可以在“常规” Windows服务部分(即不使用WCF的部分)内重用这些存储库和其他注册吗?因为我不确定WcfOperationLifestyle是否会对他们产生影响.

每当要执行需要一个或多个存储库的石英作业时,我都想使用短暂的生活方式.并且,当该作业运行时,显然可以进行WCF调用,然后应独立于计划作业中当前正在使用的存储库使用一个新的存储库实例.

我应该创建新的注册吗?如果是这样,我该如何从执行代码中调用它们?

谢谢

解决方法:

任何组件都不太可能在应用程序(WCF)的一部分中具有范围化的生活方式,而在另一部分中充当瞬态.在您的情况下,您的工作单元很有可能也必须在Quartz中进行作用域划分,但是由于没有隐式作用域(例如HTTP请求,WCF会话等),您将必须显式启动/结束某些作用域在其中运行操作并进行相应注册.

在Simple Injector中,有几种隐式技术特定范围的生活方式,例如:

> WebApiRequestLifestyle
> WebRequestLifestyle
> WcfOperationLifestyle

明确的scped生活方式是:

> LifetimeScopeLifestyle(定义了
特定于线程的范围)
> ExecutionContextScopingLifestyle(定义异步上下文特定的作用域).

因此,在Quartz中运行时,您的工作单元应具有LifetimeScopeLifestyle或ExecutionContextScopeLifestyle.两者之间的选择很容易:如果操作是异步的,并且您的方法返回Task< T&gt ;,则需要ExecutionContextScopeLifestyle,否则需要LifetimeScopeLifestyle. This Q/A提供了有关如何启动Quartz的更多信息.

因此,考虑到这一点,我认为您基本上有三种选择:

>将这两个服务(WCF和Quartz)看作是两个独立的应用程序,它们恰好位于同一个AppDomain中,并使用各自的SimpleInjector.Container实例创建两个Composition Roots. (您可能还需要考虑将服务真正分成两个单独的服务应用程序)
>您放弃WCF生活方式,并在解析执行该操作的服务之前,在每个WCF操作中明确启动新的LifetimeScope.
>将这两个服务视为一个固有整体,并使用一个容器拥有一个复合根,但是请在WCF服务类中继续使用依赖项注入.这意味着您将不得不使用混合生活方式来获得适当的生活方式.

哪种选择最适合您,取决于许多因素.例如,创建两个合成根可能真的很容易,并且通过将公用注册提取到共享方法中,可以使合成根非常易于维护.所有范围化的生活方式都从ScopedLifestyle继承,这使您可以让此共享方法接受ScopedLifestyle,该方法使共享方法不必为它调用的服务.当变得困难时,就是在整个AppDomain中实际上只有一个实例必须处于活动状态的组件(因为Singleton意味着“每个容器一个”).

不必让WCF服务具有任何逻辑,而是可以使它们真正变薄,这只是WCF,IOC容器和应用程序之间的粘合剂.因此,不必在WCF服务中注入依赖关系,而只需在调用WCF操作时解析实际的服务即可:

[OperationContract]
public SomeData DoSomething() {
    using (Bootstrapper.Container.BeginLifetimeScope()) {
        return Bootstrapper.Container.GetInstance<IDoSomethingService>()
            .DoSomething();
    }
}

这使您可以使用相同的LifetimeScopeLifestyle注册所有作用域组件.当您具有消息驱动的体系结构时,此模型非常有效,因为这意味着您的WCF层最多包含两种方法,可以读取here.这种方法可以使事情变得更容易,因为WcfOperationLifestyle有一些意外行为,因为它不会“按WCF操作”缓存服务,而是在WCF服务类(包含这些操作方法的类)期间进行缓存,最后由WCF和您的配置确定此类服务的有效期.可以是PerCall, PerSession or even Single.

但是,这种方法的缺点是,如果您拥有非常广泛的WCF服务(具有许多方法),则可能需要大量重构才能达到此目的,并在WCF服务类中进行很多仪式.

第三种选择是使用混合生活方式,如下所示:

ScopedLifestyle hybridLifestyle = Lifestyle.CreateHybrid(
    container.GetCurrentWcfOperationScope() != null,
    new WcfOperationLifestyle(),
    new LifetimeScopeLifestyle());

container.Register<IUnitOfWork, UnitOfWork>(hybridLifestyle);

您可以将此hybridLifestyle用作生活方式来注册实例.这样,您的配置就可以同时在WCF和WCF之间使用.当然,这意味着您将必须明确地启动生存期范围,如here所述.

标签:quartz-net,windows-services,wcf,c,simple-injector
来源: https://codeday.me/bug/20191121/2055392.html