如何使用SimpleInjector作为Singleton实例重新创建WCF服务(使用Tridion)
我正在使用IoC容器SimpleInjector。 我知道单身人士不应该被重新创建,因为这不是他们的目的,但我的问题是在WCF和当它进入Faulted状态,根据几次阅读它不能恢复,并需要创建一个新的实例。如何使用SimpleInjector作为Singleton实例重新创建WCF服务(使用Tridion)
我有一个名为CoreServiceService的类,它使用了两个WCF服务。
- CoreService
- 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
@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
}
}
}
}
我第二种方法,并成功地多次使用它。然而,保持IoC的精神,我通常所做的就是注入一个在IoC中注册的Func
你可以添加一个方法到您的实例,迫使某种形式的更新/刷新?你能分享你的客户代码吗? –
@StinkyTowel添加部分代码 – polonskyg
您可以添加创建** ISessionAwareCoreService sessionAwareEclServiceClient **的具体客户端的代码吗? –