0

按照此处的教程,我将在 Windows 服务中自行托管 WCF 服务。我的 WCF 服务包含一个我定期更新的全局对象。我想将该对象序列化为 JSON 并通过服务端点返回该 JSON 字符串。当我访问在服务上调用 serialize 方法的端点时,我得到了似乎是全局的全新实例。该服务设置为[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

我以与教程相同的方式实例化:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyWindowsService: ServiceBase
{public ServiceHost serviceHost = null;

    public Service()
    {
        ServiceName = "MyService";
    }

    public static void Main()
    {
        ServiceBase.Run(new MyWindowsService());
    }

    protected override void OnStart(string[] args)
    {
        if (serviceHost != null)
        {
            serviceHost.Close();
        }

        serviceHost = new ServiceHost(typeof(MyWCFService));
        serviceHost.Open();
    }

    protected override void OnStop()
    {
        if (serviceHost != null)
        {
            serviceHost.Close();
            serviceHost = null;
        }
    }

我的 WCF 服务如下所示:

public class MyWCFService: IWCFService
{
    private myObject = mySerializableObject;

    public MyWCFService()
    {
        myObject = new MySerializableObject();
        myObject.Init();
    }

    public Stream GetJSON()
    {
        MemoryStream stream = new MemoryStream();
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(MySerializableObject));

        ser.WriteObject(stream, myObject);

        string jsonString = Encoding.ASCII.GetString(stream.ToArray());


        byte[] resultBytes = Encoding.UTF8.GetBytes(jsonString);
        WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
        return new MemoryStream(resultBytes);
    }
}

如果我GET是 GetJSON 端点,则返回的字符串是对象的全新初始化。如果我中断 GetJSON 方法,myObject 会显示所有新初始化的值。在 MySerializableObject 更新代码中放置断点表明更新正确发生并保存到内存中的对象中。

在普通控制台应用程序中运行相同的代码可以正常工作。为什么会出现差异?我是否错误地处理了全局?

4

1 回答 1

0

想通了……我遇到了几个问题。

  1. 如此处所示,我的 InstanceContextMode 声明没有装饰正确的服务,因此它仍在默认的每次调用上下文中运行 - 因此,每个连接上都有一个新的状态对象。
  2. O'Reilly向我展示了我没有正确创建我的单例实例。旁注,当使用实例创建 ServiceHost 时,您可以在构造函数或 App.config 中显式指定基本 URI。这让我有些困惑,因为我遇到的许多示例都是在构造函数而不是配置中传递它的。

这是我的后代工作实现:

[ServiceContract(Namespace = "http://my.super.original.namespace")]
public interface IWCFService
{
    [OperationContract, WebGet]
    Stream GetJSON();
}

//Decorator goes on WCF service, not the Windows service
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyWCFService : IWCFService
{
    private StateObject _myStateObject;

    public MyWCFService()
    {
        _myStateObject = new StateObject();
        _myStateObject.Init();
    }

    public Stream GetJSON()
    {
        .
        .
        .
        return "JSON String Here";
    }
}

public class MyWindowsService : ServiceBase
{
    public ServiceHost serviceHost = null;
    private readonly MyWcfService _wcfSingleton;

    public MyWindowsService()
    {
        ServiceName = "WindowsServiceNameHere";
        _wcfSingleton = new MyWCFService();
    }

    public static void Main()
    {
        ServiceBase.Run(new MyWindowsService());
    }

    // Start the Windows service.
    protected override void OnStart(string[] args)
    {
        if (serviceHost != null)
        {
            serviceHost.Close();
        }

        //load WCF Singleton Instance and open it for connections
        serviceHost = new ServiceHost(_wcfSingleton);
        serviceHost.Open();
    }

    protected override void OnStop()
    {
        if (serviceHost != null)
        {
            serviceHost.Close();
            serviceHost = null;
        }
    }
}
于 2019-01-21T19:10:19.203 回答