如何使用SimpleInjector将WCF服务重新创建为Singleton实例(使用Tridion)

时间:2017-10-09 18:01:04

标签: c# wcf ioc-container simple-injector tridion-core-services

我正在使用IoC Container SimpleInjector。 我知道Singletons不应该重新创建,因为那不是他们的目的,但我的问题是WCF,当它进入 Faulted 状态时,根据几个读数,它无法恢复,并且需要一个新的实例创建

我有一个名为CoreServiceService的类,它使用两个WCF服务。

  1. CoreService
  2. ECLService
  3. 我希望这些服务是单例服务,因为我将对CoreServiceSession进行大量调用,并且创建这些WCF服务太昂贵并且需要很多次,在创建之后,它们会更快。

    我正在将它们注册为:

    container.Register(() => new SessionAwareEclServiceClient(binding, eclServiceRemoteAddress), Lifestyle.Singleton);
    
    container.Register(() => new SessionAwareCoreServiceClient(binding, coreServiceRemoteAddress), Lifestyle.Singleton);
    
    container.Register(typeof(ICoreServiceSession), typeof(CoreServiceSession), Lifestyle.Scoped);
    

    我的问题是,如果无法检索到某些内容而使用ECLService,则会进入 Faulted 连接,在这种情况下,我会调用.Abort()并关闭连接。但是下次我调用我的服务时ECLService WCF服务一直处于Faulted状态(因为它是一个单例)所以我需要一种方法来重新创建连接。

    我试过像

    这样的东西
    coreServiceSession.EclServiceClient = (SessionAwareEclServiceClient)container.GetInstance(typeof(SessionAwareEclServiceClient));
    

    但是,当然,它给了我相同的实例。

    我也尝试过使用这个初始化程序

    container.RegisterInitializer<ICoreServiceSession>(coreServiceSession =>
    {
        if (coreServiceSession.EclServiceClient.State == CommunicationState.Faulted)
        {
            coreServiceSession.EclServiceClient.Abort();
            coreServiceSession.EclServiceClient = null;
            coreServiceSession.EclServiceClient = (SessionAwareEclServiceClient)container.GetInstance(typeof(SessionAwareEclServiceClient));
        }
    }
    

    同样的事情我尝试使用而不是容器.GetInstance,这个:

    coreServiceSession.EclServiceClient = new SessionAwareEclServiceClient(binding, eclServiceRemoteAddress);
    

    同样的事情。任何想法/选项?

    无论如何,在这种情况下强行要获得一个新实例?

    更新

    这是CoreServiceSession类的一部分

    public class CoreServiceSession : ICoreServiceSession
    {
          public CoreServiceSession(ISessionAwareCoreService sessionAwareEclServiceClient, SessionAwareCoreServiceClient sessionAwareCoreServiceClient)
            {
                EclServiceClient = sessionAwareEclServiceClient;
                CoreServiceClient = sessionAwareCoreServiceClient;
            }
    
            public ISessionAwareCoreService EclServiceClient { get; set; }
    
            public SessionAwareCoreServiceClient CoreServiceClient { get; set; }
    
            public string CreateOrGetStubUris(string eclItemUri)
            {
                var stubInfo = EclServiceClient.CreateOrGetStubUris(new List<string> { eclItemUri }).FirstOrDefault();
            }
    }
    

    提前致谢。吉列尔莫

1 个答案:

答案 0 :(得分:1)

@ScottHannen在评论中已经给出了答案:不要将频道注册为单身:创建它们并不昂贵,只有频道工厂才有。

事实上,您根本不应将WCF客户端对象注入构造函数中。将它们注入构造函数意味着它们是一个有用的抽象,可用于拦截,模拟或替换,而使用此类客户端的类通常与WCF强耦合。

因此,不要将它们注入构造函数,而是让消费者使用ChannelFactory在内部创建它们。即使这样ChannelFactory通常也不必注入,您可以在私有静态字段中新建它。

这就是CoreServiceSession的样子:

public class CoreServiceSession : ICoreServiceSession
{
    private static readonly ChannelFactory factory =
        new ChannelFactory<ISessionAwareCoreService>(myBinding, myEndpoint);

    public string CreateOrGetStubUris(string eclItemUri)
    {
        var client = factory.CreateChannel();

        try
        {
            return EclServiceClient.CreateOrGetStubUris(
                new List<string> { eclItemUri }).FirstOrDefault();
        }
        finally
        {
            try
            {
                ((IDisposable)client).Dispose();
            }
            catch
            {
                // We need to swallow exceptions thrown by Dispose. 
                // See: https://marcgravell.blogspot.com/2008/11/dontdontuse-using.html
            }
        }
    }
}