自托管WCF服务:如何从托管应用程序访问实现服务合同的对象? [英] Self-hosted WCF service: How to access the object(s) implementing the service contract from the hosting application?

查看:142
本文介绍了自托管WCF服务:如何从托管应用程序访问实现服务合同的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在WPF客户端自主托管WCF服务。我想显示服务在用户界面中接收到的数据。每次收到一些数据时,应更新用户界面。



App.xaml.cs中的代码看起来像

  private ServiceHost _host = new ServiceHost(typeof(MyService)); 

private void Application_Startup(object sender,StartupEventArgs e)
{
_host.Open();
}

private void Application_Exit(object sender,ExitEventArgs e)
{
_host.Close();
}

如何从...中获取实现服务合同的对象实例托管WPF应用程序?






感谢大家的答案。



我没看到的是ServiceHost的构造函数允许通过服务的实例,而不是类型



所以我现在做的是:




  • 在服务实现中使用ObservableCollection

  • 将服务配置为单例(请参阅burnburnmonk的注释)

  • 绑定到WPF应用程序中的ObservableCollection

  • 获取服务实例使用数据绑定属性 DataContext

  • 将其传递给ServiceHost的构造函数



结果:单例WCF服务中的每个更新



快乐!

解决方案

as marc_s说,您正在创建一个PerCall / PerSession WCF服务,并在每个会话的每个请求/第一个请求上创建一个新的实例。



您可以在其周围建立一些管道,以便实例可以在收到新请求时通知服务主机,但这不会是一个简单的练习,您需要如果您决定使用事件来执行此操作,请注意内存泄漏的可能性 - 如果不执行弱事件模式,那么您的WCF服务实例可能会被挂起,因为事件处理程序仍然保留对它们的引用,除非您记住通知主机在WCF服务实例被处理时取消订阅。



相反,这里有两个想法可能会更容易实现您的目标:



使用单个 InstanceContextMode ,如果您的服务可以是单例,在这种情况下,您将创建一个实现您的服务合同并托管它的新实例:

  // insta nce将是你的WCF服务实例
private ServiceHost _host = new ServiceHost(instance);

这样您就可以访问将检索客户端请求的实例。



或者,您可以让所有托管的实例都是虚拟的fascades,它们共享一个实际处理请求的静态类:

  [ServiceContract] 
接口IMyService {...}

接口IMyServiceFascade:IMyService {...}

//虚函数
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall]
public class MyServiceFascade:IMyServiceFascade
{
private static IMyService _serviceInstance = new MyService();

public static IMyService ServiceInstance {get {return _serviceInstance;}}

public int MyMethod()
{
return _serviceInstance.MyMethod();
}
...
}

//执行工作的逻辑类
public class MyService:IMyService {...}

//然后主持th e fascade
var host = new ServiceHost(typeof(MyServiceFascade));

//但您仍然可以访问实际的服务类
var serviceInstance = MyServiceFascade.ServiceInstance;

我想说,如果可能,你应该采用第一种方法,使生活更容易! / p>

I am self-hosting a WCF service in a WPF client. I want to show the data the service receives in the user interface. Every time some data is received the user interface should be updated.

The code in "App.xaml.cs" looks like

    private ServiceHost _host = new ServiceHost(typeof(MyService));

    private void Application_Startup(object sender, StartupEventArgs e)
    {
        _host.Open();
    }

    private void Application_Exit(object sender, ExitEventArgs e)
    {
        _host.Close();
    }

How can I get the object instance(s) implementing the service contract from the hosting WPF application?


Thanks everybody for the answers.

What I didn't see was that the constructor of ServiceHost allows to pass an instance of the service instead of its type.

So what I do now is:

  • Use an ObservableCollection in the service implementation
  • Configure the service to be a singleton (see theburningmonk's comment)
  • Bind to the ObservableCollection in my WPF application
  • Get an instance of the service using the databinding property DataContext
  • Pass it to the constructor of ServiceHost

Result: Every update in the singleton WCF service is reflected in the UI.

Happy!

解决方案

As marc_s said, you're creating a PerCall/PerSession WCF service and a new instance is created on every request/first request of every session.

You could build some plumbing around it so that the instance can notify the service host when it receives a new request but it won't be an easy exercise and you need to be mindful of the potential for memory leak if you decide to go with using events to do this - without implementing the Weak Event Pattern your WCF service instances could be left hanging around as the event handlers still holds a reference to them UNLESS you remember to notify the host to unsubscribe when the WCF service instances are disposed.

Instead, here's two ideas which might make it easier for you to achieve your goal:

Use the Single InstanceContextMode if your service can be made a singleton, in which case you will create a new instance which implements your service contract and host it:

// instance will be your WCF service instance
private ServiceHost _host = new ServiceHost(instance); 

that way you will have access to the instance that will retrieve the client requests.

Alternatively, you could have all the hosted instances be dummy 'fascades' which share a static class that actually process the requests:

[ServiceContract]
interface IMyService { ... }

interface IMyServiceFascade : IMyService { ... }

// dummy fascade
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall]
public class MyServiceFascade : IMyServiceFascade 
{ 
    private static IMyService _serviceInstance = new MyService();

    public static IMyService ServiceInstance { get { return _serviceInstance; } }

    public int MyMethod()
    {
       return _serviceInstance.MyMethod();
    }
    ... 
}

// the logic class that does the work
public class MyService : IMyService { ... }

// then host the fascade
var host = new ServiceHost(typeof(MyServiceFascade));

// but you can still access the actual service class
var serviceInstance = MyServiceFascade.ServiceInstance;

I'd say you should go with the first approach if possible, makes life that bit easier!

这篇关于自托管WCF服务:如何从托管应用程序访问实现服务合同的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆