Могу ли я вызвать метод в собственной службе WCF локально? - PullRequest
9 голосов
/ 20 мая 2011

У меня есть контракт службы WCF, который в основном является шаблоном публикации подписчика.

Служба WCF размещена внутри службы Windows, из которой я хочу публиковать.Клиенты подписываются на сообщения, и когда служба Windows делает что-то, что она публикует всем клиентам.

Для размещения службы я объявил класс ServiceHost, а в классе контракта есть метод, который не помечен в интерфейсе, нореализован в классе для публикации.

Я хочу иметь возможность вызывать этот метод локально (не проходя через WCF), который затем публикует сообщение через обратные вызовы.

Я не могу получитьот ServiceHost до экземпляра класса контракта.

Возможно ли это, и если да, то как?Я знаю, что обходной путь состоит в том, чтобы встроить клиент в службу, но кажется немного странным создание клиента для подключения к себе.

Заранее спасибо

DJIDave

app.config

<system.serviceModel>
    <services>
      <service behaviorConfiguration="Processor.Wcf.ServiceBehavior"
        name="Processor.Wcf.ProcessorService">
        <endpoint address="net.tcp://localhost:9000/processor/service"
              binding="netTcpBinding" name="procService"
              bindingConfiguration="netTcpBindingConfig"
              contract="Processor.Wcf.IProcessorService"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
          <host>
            <baseAddresses>
              <add baseAddress="http://localhost:8732/Design_Time_Addresses/Processor.Wcf/Service1/" />
            </baseAddresses>
          </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="Processor.Wcf.ServiceBehavior">
          <!-- To avoid disclosing metadata information, 
          set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <netTcpBinding>
        <binding name="netTcpBindingConfig"
                 closeTimeout="00:01:00"
                 openTimeout="00:01:00"
                 receiveTimeout="00:10:00"
                 sendTimeout="00:01:00"
                 transactionFlow="false"
                 transferMode="Buffered"
                 transactionProtocol="OleTransactions"
                 hostNameComparisonMode="StrongWildcard"
                 listenBacklog="10"
                 maxBufferPoolSize="524288"
                 maxBufferSize="65536"
                 maxConnections="10"
                 maxReceivedMessageSize="65536">
          <readerQuotas maxDepth="32"
                        maxStringContentLength="8192"
                        maxArrayLength="16384"
                        maxBytesPerRead="4096"
                        maxNameTableCharCount="16384" />
          <reliableSession ordered="true"
                           inactivityTimeout="00:10:00"
                           enabled="false" />
          <security mode="Transport">
            <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
          </security>
        </binding>
      </netTcpBinding>
    </bindings>

  </system.serviceModel>

Ответы [ 4 ]

8 голосов
/ 20 мая 2011

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

Чтобы сохранить службу в том виде, как она настроена, вам придется вызывать ее через клиента. Это на самом деле проще, чем вы думаете. Поскольку у вашего хост-кода есть доступ к контракту на обслуживание, вы можете использовать его с классом ChannelFactory , чтобы получить прокси для сервиса. Кроме контракта на обслуживание, все, что вам нужно предоставить, это конечная точка name , а ChannelFactory сделает все остальное. Ниже приведен пример того, как это сделать:

private IMyServiceContract GetLocalClient(string serviceEndpointName)
{
    var factory = new ChannelFactory<IMyServiceContract>(serviceEndpointName);
    return factory.CreateChannel();
}

UPDATE: Наряду с этим подходом вы должны рассмотреть возможность предоставления вашей службе конечной точки NetNamedPipeBinding для повышения производительности. Эта привязка в значительной степени делает все в памяти и является самой быстрой привязкой для вызова службы той же машины.

3 голосов
/ 19 апреля 2012

Для службы WCF, создающей несколько экземпляров (не одноэлементной), вы можете вести список, содержащий соответствующую функцию обратного вызова каждого экземпляра, как указано здесь: mdsn .Вы можете вызвать метод CallClients () (из этого примера MSDN) непосредственно из кода хостинга, так как он является статическим членом класса обслуживания.Это единственный другой способ, который я нашел ..

1 голос
/ 02 марта 2018

Если вы не предоставите ссылку на экземпляр службы на ServiceHost в качестве параметра конструктора,

Эта строка из решения Sixto решила для меня кое-что.Благодарю, а также этот пост .

В настоящее время я использую дуплексную привязку.


Ключевая концепция заключается в том, что вы можете передать Type или экземпляр вServiceHost конструктор.

Итак, что у меня было раньше:

 ServiceHost host = new ServiceHost(typeof(MyService), myUri);

Мне нужно было:

 MyService service = new MyService(foo);  // Can now pass a parameter
 ServiceHost host = new ServiceHost(service, myUri);

Кроме того, мне нужно было отметить MyServiceс

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 

... и теперь я могу вызывать методы хоста изнутри сервиса.

Однако имейте в виду, что созданный вами экземпляр не будет иметь OperationContext, если вы вызываете его методы напрямую: https://stackoverflow.com/a/15270541/385273

Удачи!

0 голосов
/ 04 апреля 2019

Старый вопрос, но здесь - это еще один способ вызова Singleton WCF Service hosted on a Windows Service

В соответствии с требованиями @ Бена, Service необходимо будет принудительно вызватьбыть Singleton:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 

Тогда:

var host = new ServiceHost(typeof(MyService), myUri);
var instance = (MyService)host.SingletonInstance;

Вот и все.По сути, у хоста уже есть свойство, которое необходимо «привести», чтобы иметь возможность доступа ко всем функциям из Service.

...