【问题标题】:How to recreate a WCF Service as Singleton instance with SimpleInjector (using Tridion)如何使用 SimpleInjector 将 WCF 服务重新创建为 Singleton 实例(使用 Tridion)
【发布时间】:2018-03-21 00:21:39
【问题描述】:

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

我有一个名为 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 时,如果无法检索某些内容,则会进入 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));
    }
}

同样的事情,我尝试用 container.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();
    }
}

提前致谢。吉列尔莫

【问题讨论】:

  • 您可以向您的实例添加一种方法来强制进行某种更新/刷新吗?你能分享你的客户端代码吗?
  • @StinkyTowel 添加了部分代码
  • 能否添加创建ISessionAwareCoreService sessionAwareEclServiceClient的具体客户端的代码?
  • 这是由 IoC 容器创建的
  • Here's an interesting post.。总而言之 - 它说让ChannelFactory 成为单例,因为那是昂贵的部分。但不要让客户成为单身人士。

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


【解决方案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
            }
        }
    }
}

【讨论】:

  • 我支持这种方法,并成功使用过很多次。但是,本着 IoC 的精神,我通常所做的是注入一个在 IoC 中注册的 Func(),并且 lambda 负责使用单例 ChannelFactory。还可以编写扩展方法来执行客户端的 CleanClose(Try-Finally 块中的部分
猜你喜欢
  • 1970-01-01
  • 2012-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-19
  • 1970-01-01
  • 2012-01-12
相关资源
最近更新 更多