2017-10-09 57 views
0

我正在使用IoC容器SimpleInjector。 我知道单身人士不应该被重新创建,因为这不是他们的目的,但我的问题是在WCF和当它进入Faulted状态,根据几次阅读它不能恢复,并需要创建一个新的实例。如何使用SimpleInjector作为Singleton实例重新创建WCF服务(使用Tridion)

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

  1. CoreService
  2. ECLService

我想这些服务是单身,因为我会打很多电话给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如果事情无法检索是进入故障连接,在),这种情况下,我打电话.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)); 
    } 
} 

同样的事情试过,我试图用的,而不是container.GetInstance,这样的:

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

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

无论如何强迫在这种情况下得到一个新的实例吗?

UPDATE

这是类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(); 
     } 
} 

预先感谢的一部分。 Guillermo

+0

你可以添加一个方法到您的实例,迫使某种形式的更新/刷新?你能分享你的客户代码吗? –

+0

@StinkyTowel添加部分代码 – polonskyg

+0

您可以添加创建** ISessionAwareCoreService sessionAwareEclServiceClient **的具体客户端的代码吗? –

回答

0

@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 
      } 
     } 
    } 
} 
+1

我第二种方法,并成功地多次使用它。然而,保持IoC的精神,我通常所做的就是注入一个在IoC中注册的Func (),并且lambda负责使用单例ChannelFactory。 也可以编写扩展方法来执行客户端的CleanClose(Try-Finally块中的部分 – KRam

相关问题