WCF: доступ к экземпляру службы с сервера


Контекст:

Мне нужно разработать сервер мониторинга, который отслеживает некоторые из наших приложений (эти приложения находятся в c#). Поэтому я решил разработать систему с WCF, которая кажется подходящей для моих нужд.

Эти приложения должны регистрироваться на сервере мониторинга при запуске. После этого сервер мониторинга может вызвать методы Start или Stop этих приложений.

Все полностью выполняется на одной машине, ничего должен быть выполнен удаленно.

Поэтому я разработал хороший прототип, и все работает отлично. Каждое приложение регистрируется на сервере мониторинга.

Вопрос:

ApplicationRegistrationService (смотрите код ниже) является реализацией службы мониторинга, и это одноэлементный экземпляр из-за атрибута ServiceBehavior.

Вот моя проблема: я хочу получить доступ к содержимому ApplicationRegistrationService в каждом примере, количество подключенных приложений с моего сервера (ConsoleMonitoringServer в Примере). Но я не знаю, как этого добиться.

Нужно ли мне создать канал в моем сервере к службе, как я сделал в моих клиентах (ConsoleClient), или существует лучший способ достичь этого?

Код:

Код очень упрощен для целей этого вопроса:

//The callback contract interface
public interface IApplicationAction
{
    [OperationContract(IsOneWay = true)]
    void Stop();

    [OperationContract(IsOneWay = true)]
    void Start();
}

[ServiceContract(SessionMode = SessionMode.Required, 
    CallbackContract = typeof(IApplicationAction))]
public interface IApplicationRegistration
{
    [OperationContract]
    void Register(Guid guid, string name);

    [OperationContract]
    void Unregister(Guid guid);
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, 
    ConcurrencyMode = ConcurrencyMode.Multiple)]
public class ApplicationRegistrationService : IApplicationRegistration
{
    //IApplicationRegistration Implementation
}

public class ApplicationAction : IApplicationAction
{
    //IApplicationAction Implementation
}

Консольное приложение для этого примера

class ConsoleClient
{
    static void Main(string[] args)
    {
        ApplicationAction actions = new ApplicationAction();

        DuplexChannelFactory<IApplicationRegistration> appRegPipeFactory =
            new DuplexChannelFactory<IApplicationRegistration>(actions,
            new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/AppReg"));

        IApplicationRegistration proxy = appRegPipeFactory.CreateChannel();
        proxy.Register(Guid.Empty, "ThisClientName");

        //Do stuffs
    }
}

Консольный сервер для этого примера

class ConsoleMonitoringServer
{
    static void Main(string[] args)
    {
        using (ServiceHost host = new ServiceHost(typeof(ApplicationRegistrationService),
            new Uri[]{ new Uri("net.pipe://localhost")}))
        {
            host.AddServiceEndpoint(typeof(IApplicationRegistration), 
                new NetNamedPipeBinding(), "AppReg");

            host.Open();

            //Wait until some write something in the console
            Console.ReadLine();

            host.Close();
        }
    }
}
2 6

2 ответа:

Наконец, я нашел ответ, и это было довольно легко. Мне просто нужно создать экземпляр службы и передать ссылку на конструктор ServiceHost.

Поэтому мне нужно заменить следующий код:

using (ServiceHost host = new ServiceHost(typeof(ApplicationRegistrationService),
                new Uri[]{ new Uri("net.pipe://localhost")}))

By:

ApplicationRegistrationService myService = new ApplicationRegistrationService();

using (ServiceHost host = new ServiceHost(myService,
                new Uri[]{ new Uri("net.pipe://localhost")}))

Если вы хотите установить двустороннюю связь между службой мониторинга и зарегистрированными службами или узлами, то вам, вероятно, следует использовать двустороннюю связь в WCF, также известную как двусторонняя связь. Очень классная штука.

Http://www.codeproject.com/KB/WCF/WCF_Duplex_UI_Threads.aspx