Самостоятельно размещенный глобальный объект службы WCF создается заново каждый раз, когда вызывается конечная точка - PullRequest
0 голосов
/ 21 января 2019

Следуя инструкции здесь Я сам размещаю службу WCF внутри службы Windows.Моя служба 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 показывает, что обновления выполняются правильно и сохраняются в объекте в памяти.

Выполнение того же кода в обычном консольном приложении работает нормально.Почему расхождение?Я неправильно обращаюсь с глобальным?

1 Ответ

0 голосов
/ 21 января 2019

Разобрался ... У меня было несколько проблем.

  1. Как указано здесь , мое объявление InstanceContextMode не украшал правильную услугу, поэтому он все еще работал в контекст по умолчанию для каждого вызова - следовательно, новый объект состояния для каждого соединения.
  2. О'Рейли показал мне, что я не создавал свой синглтон пример правильно. Примечание: при создании ServiceHost с использованием экземпляра вы можете явно указать базовый URI в конструкторе или в App.config. Это вызвало у меня некоторую путаницу, так как многие примеры, с которыми я сталкивался, передавались в конструкторе, а не в конфиге.

Вот моя рабочая реализация для потомков:

[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;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...