【问题标题】:Setting variable from ServiceHost从 ServiceHost 设置变量
【发布时间】:2013-06-03 17:03:40
【问题描述】:

在我的项目中,我有一个服务类。

class KLAService : IKLAService
{
    CentralLogic centralLogic;

    .....
}

使用这个类,我这样设置ServiceHost

centralLogic = new CentralLogic();

ServiceHost host = new ServiceHost(typeof(KLAService));
using (host)
{ 
    host.Open();

    Application app = new Application();
    app.Run(new ConfigurationWPF.MainWindow(centralLogic));

    host.Close();
}

可能已经很清楚了,我创建了CentralLogic 类的一个实例。这个实例不仅在 UI 中使用,而且在主机中用于管理我的解决方案中的其他内容。

我现在遇到的问题是在KLAService-class(或host)中设置centralLogic-变量。我不知道该怎么做。我已经阅读了有关插件 Ninject 以及如何在服务中注入对象的信息,但这超出了我的范围,我不禁想到有一个简单的方法。

我怎样才能最好地实现我的目标?

编辑:提出的另一个解决方案是启动 ServiceHost 并让 CentralLogic 在那里创建,而不是相反。这意味着 ServiceHost 需要某种构造函数。我不知道最佳实践是什么,也不知道如何实现这一目标。任何帮助表示赞赏。

【问题讨论】:

标签: c# wcf web-services servicehost


【解决方案1】:

我不认为你真的需要依赖注入。由于CentralLogic 有一个实例,它实际上是一个单例。阅读单例模式here

你可以在CentralLogic上实现单例模式

public sealed class CentralLogic
{
    private static readonly Lazy<CentralLogic> lazy =
        new Lazy<CentralLogic>(() => new CentralLogic());

    public static CentralLogic Instance { get { return lazy.Value; } }

    private CentralLogic()
    {
    }
}

然后在 Service Impl 的构造器中(以及在 UI 中),您可以通过以下方式获取实例:

class KLAService : IKLAService
{
    CentralLogic m_centralLogic;

    public KLAService() 
    {
       m_centralLogic = CentralLogic.Instance;
       ....
    }
}

无需向 ServiceHost 传递任何内容。

对您来说最重要的是确保您的 CentralLogic 的实例是线程安全的。

【讨论】:

  • 这更像是,我不明白为什么一切都必须如此困难。在ServiceHost,如何调用构造函数?我遇到了麻烦。另一方面,我真的不需要声明m_centralLogic 的构造函数,但可以使用例如CentralLogic.Instance.GetUsers();。让我试试这个。
  • KLAService 构造函数应该没有问题 - 毕竟它是默认(无参数)构造函数 - WCF 会处理它。是的,您可以使用 - CentralLogic.Instance.Methods() - 请确保 CentralLogic 类的所有方法和属性在其实现中都是线程安全的。
【解决方案2】:

最简单的解决方案是为CentralLogic 类创建一个单例。

如果你想做依赖注入,我推荐structuremap,你可以用nuget很容易地设置它,我建议你在KLAService中进行注入

这是一个控制台应用程序,展示了如何设置它并将一些本地对象注入其他类:

class KLAService : IKLAService
{
    // Constructor injection
    public KLAService(ICentralLogic logic)
    {
        Console.WriteLine(logic.Value);
    }

    // Manual instance creation
    internal void PrintLogicValue()
    {
        var logic = ObjectFactory.Container.GetInstance<ICentralLogic>();
        Console.WriteLine(logic.Value);
    }
}

interface IKLAService
{
}

class CentralLogic : ICentralLogic
{
    public int Value { get; set; }

    public CentralLogic()
    {
        Value = 12345;
    }
}

interface ICentralLogic
{
    int Value { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var logic = new CentralLogic();

        ObjectFactory.Initialize(x => x.Scan(scan => scan.TheCallingAssembly()));
        ObjectFactory.Container.Configure(x => x.For<ICentralLogic>().Use(y => logic));

        var service = ObjectFactory.Container.GetInstance<KLAService>();
        service.PrintLogicValue();

        Console.ReadKey();
    }
}

当代码调用var service = ObjectFactory.Container.GetInstance&lt;KLAService&gt;(); 时,构造函数需要ICentralLogic 类型的对象,而注入器将提供配置的logic 对象。

或者,您可以使用ObjectFactory.Container.GetInstance&lt;ICentralLogic&gt;(); 手动获取ICentralLogic 的配置对象。

【讨论】:

  • 这是有道理的。在此处创建ServiceHost 如何适合?
  • 最简单的方法是把new ServiceHost(typeof(KLAService))改成new ServiceHost(ObjectFactory.Container.GetInstance&lt;KLAService&gt;())
  • 好的,让我试试这个。你能向我解释一下你对这两条ObjectFactory 线做了什么吗?之后,您声明var service。我可以在new ServiceHost... 行中使用service,对吗?
  • ObjectFactory.Initialize 初始化结构图以扫描调用程序集的类型,即当前运行的应用程序。第二行ObjectFactory.Container.Configure 告诉它,只要您需要一个带有ObjectFactory.Container.GetInstance 的实例,您将获得一个已配置的对象。您的代码将变为:ServiceHost host = new ServiceHost(ObjectFactory.Container.GetInstance&lt;KLAService&gt;());
  • Singleton 非常适合快速解决问题,而且我在许多项目中也使用过它们。但是,当您必须进行单元测试时,配置所有单例将非常麻烦。如果您打算进行单元测试,我真的会敦促您远离单例,它们太让人头疼,难以维护和配置,尤其是如果您想编写其他人可重用的代码。
猜你喜欢
  • 1970-01-01
  • 2019-12-25
  • 2013-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-24
  • 1970-01-01
相关资源
最近更新 更多