如何使一个WCF接口,利用在服务中声明的变量 [英] How to make a WCF interface utilize variables declared in a service

查看:109
本文介绍了如何使一个WCF接口,利用在服务中声明的变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我跟着MSDN教程这里为了使与WCF服务。我关心的是如何访问 CalculatorWindowService 声明的变量从 CalculatorService的,这样我可以修改它以备后用价值在 CalculatorWindowService 例如,如果在添加方法,减,除,和乘,如果我还想要的结果将被存储到列表<双> ; DoubleList CalculatorWindowService

宣布

 使用系统; 
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;

使用System.ComponentModel;
使用System.ServiceModel;
使用System.ServiceProcess;
使用System.Configuration;
使用System.Configuration.Install;

命名空间Microsoft.ServiceModel.Samples
{
//定义一个服务合同。
[的ServiceContract(命名空间=HTTP://Microsoft.ServiceModel.Samples)]
公共接口ICalculator
{
[OperationContract的]
双增(双N1双N2);
[OperationContract的]
双减(双N1,N2双);
[OperationContract的]
双乘(双N1,N2双);
[OperationContract的]
双分频(双N1,N2双);
}

//实现在服务类ICalculator服务合同。
公共类CalculatorService的:ICalculator
{
//实施ICalculator方法。
公共双增(双N1,N2双)
{
双重结果= N1 + N2;
返回结果;
}

公共双减(双N1,N2双)
{
双重结果= N1 - N2;
返回结果;
}

公共双乘(双N1,N2双)
{
双重结果= N1 N2 *;
返回结果;
}

公共双分频(双N1,N2双)
{
双重结果= N1 / N2;
返回结果;
}
}

公共类CalculatorWindowsService:ServiceBase
{
公开名单<双> DoubleList =新的List< INT>();
公众的ServiceHost的ServiceHost = NULL;
公共CalculatorWindowsService()
{
//命名Windows服务
服务名称=WCFWindowsServiceSample;
}

公共静态无效的主要()
{
ServiceBase.Run(新CalculatorWindowsService());
}

//启动Windows服务。
保护覆盖无效的OnStart(字串[] args)
{
如果(ServiceHost的!= NULL)
{
serviceHost.Close();
}

//创建用于CalculatorService的类型和
//提供基址的ServiceHost的。
的ServiceHost =新的ServiceHost(typeof运算(CalculatorService的));

//打开ServiceHostBase创建监听器,启动
//监听消息。
serviceHost.Open();
}

保护覆盖无效调用OnStop()
{
如果(ServiceHost的!= NULL)
{
serviceHost.Close();
的ServiceHost = NULL;
}
}
}

//提供了ProjectInstaller级,从而使
//由Installutil.exe工具$ B安装服务$ b [runInstaller的(真)]
公共类ProjectInstaller:安装
{
私人ServiceProcessInstaller进程;
私人的ServiceInstaller服务;

公共ProjectInstaller()
{
=过程新ServiceProcessInstaller();
process.Account = ServiceAccount.LocalSystem;
服务=新的ServiceInstaller();
service.ServiceName =WCFWindowsServiceSample;
Installers.Add(过程);
Installers.Add(服务);
}
}
}


解决方案

为了您的GUI(客户端)应用程序能够交谈的Windows服务,您需要使用进程间通信机制,因为这两个Windows服务和GUI是独立的,独立的过程。最简单的方法是创建一个 NetNamedPipe 使用 Windows通讯基础



第一部分:Windows服务



我假设你已经创建Windows服务,并知道如何部署它。因此,我们首先添加了一份合同, ICalculatorService 称为Windows服务项目(确保这个接口是在它自己的文件):

  [的ServiceContract] 
公共接口ICalculatorService
{
[OperationContract的]
无效添加(double值);

[OperationContract的]
名单,LT;双> GetAllNumbers();
}



然后,我们需要实现这个接口。创建一个名为 CalculatorService的新类(再次,在它自己的文件):

 公共类CalculatorService的:ICalculatorService 
{
私人静态列表<双> m_myValues =新的List<双>();

公共无效添加(双值)
{
m_myValues.Add(值);
}

公开名单<双> GetAllNumbers()
{
返回m_myValues;
}
}

请注意,我们有一个静态列表<双> 它包含所有的值。现在,我们需要使Windows服务的主机,以便在客户端(GUI),可以连接到它。代码隐藏在Windows服务是这样的:

 部分类CalculatorWindowsService:ServiceBase 
{
公众的ServiceHost m_host;

公共CalculatorWindowsService()
{
的InitializeComponent();
}

保护覆盖无效的OnStart(字串[] args)
{
//如果主机仍处于打开状态,首先关闭它。
如果(m_host!= NULL)
{
m_host.Close();
}

//创建一个新的主机
m_host =新的ServiceHost(typeof运算(CalculatorService的),新的URI(net.pipe:// localhost的));

//注:MyServiceAddress是一个任意名称。你可以将其更改为任何你想要的。
m_host.AddServiceEndpoint(typeof运算(ICalculatorService),新NetNamedPipeBinding(),MyServiceAddress);

m_host.Open();
}

保护覆盖无效调用OnStop()
{
//当服务停止
如果关闭主机(m_host!= NULL)
{
m_host.Close();
m_host = NULL;
}
}
}

这是我们所需要的。在对Windows服务端



第二部分:GUI(客户端)
首先,我们需要确保我们创建了一个合同就像我们在Windows服务创建的,所以客户端可以成功地使服务电话之一。要做到这一点,只需将 ICalculatorService 界面复制到客户端应用程序。请确保您更改命名空间,以便它与客户端的其他类相一致。我创建了一个简单的 Windows窗体程序有两个按钮:添加值获取所有值。这种形式背后的代码如下所示:

 公共部分Form1类:表格
{
公Form1的()
{
的InitializeComponent();
}

私人无效Form1_Load的(对象发件人,EventArgs五)
{
}

私人无效AddValue_Click(对象发件人,EventArgs的)
{使用
(的ChannelFactory< ICalculatorService>制造工厂=新的ChannelFactory< ICalculatorService>(新NetNamedPipeBinding(),新的EndpointAddress(net.pipe://本地主机/ MyServiceAddress)))
{
ICalculatorService代理= facotry.CreateChannel();

//生成一个随机数发送到服务
随机兰特=新随机();
VAR值= rand.Next(3,20);

//发送随机值到Windows服务
proxy.Add(值);
}
}

私人无效GetAllValues_Click(对象发件人,EventArgs五)
{
使用(的ChannelFactory< ICalculatorService>制造工厂=新的ChannelFactory< ICalculatorService> (新NetNamedPipeBinding(),新的EndpointAddress(net.pipe://本地主机/ MyServiceAddress)))
{
ICalculatorService代理= facotry.CreateChannel();

//获取所有从服务
变种returnedResult号码= proxy.GetAllNumbers();

//显示由服务
MessageBox.Show(的string.join(\\\
,returnedResult))返回的值;
}
}
}

下面是我的文件快照在Windows服务和WinForms项目,以帮助您看到的事情是:



在这里输入的形象描述



修改
你可以修改 m_myValues 公共,并获得它的 CalculatorWindowsService 类中。


I recently followed the MSDN tutorial HERE In order to make a service with WCF. My concern now is how to access a variable declared in CalculatorWindowService From CalculatorService so that I can modify it's value for later use in CalculatorWindowService For example if in the methods for Add,Subtract,Divide, and Multiply if I Also wanted the results to be stored into the List<double> DoubleList declared in CalculatorWindowService

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.ComponentModel;
using System.ServiceModel;
using System.ServiceProcess;
using System.Configuration;
using System.Configuration.Install;

namespace Microsoft.ServiceModel.Samples
{
    // Define a service contract.
    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
    public interface ICalculator
    {
        [OperationContract]
        double Add(double n1, double n2);
        [OperationContract]
        double Subtract(double n1, double n2);
        [OperationContract]
        double Multiply(double n1, double n2);
        [OperationContract]
        double Divide(double n1, double n2);
    }

    // Implement the ICalculator service contract in a service class.
    public class CalculatorService : ICalculator
    {
        // Implement the ICalculator methods.
        public double Add(double n1, double n2)
        {
            double result = n1 + n2;
            return result;
        }

        public double Subtract(double n1, double n2)
        {
            double result = n1 - n2;
            return result;
        }

        public double Multiply(double n1, double n2)
        {
            double result = n1 * n2;
            return result;
        }

        public double Divide(double n1, double n2)
        {
            double result = n1 / n2;
            return result;            
        }
    }

    public class CalculatorWindowsService : ServiceBase
    {
        public List<double> DoubleList = new List<int>();
        public ServiceHost serviceHost = null;
        public CalculatorWindowsService()
        {
            // Name the Windows Service
            ServiceName = "WCFWindowsServiceSample";
        }

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

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

            // Create a ServiceHost for the CalculatorService type and 
            // provide the base address.
            serviceHost = new ServiceHost(typeof(CalculatorService));

            // Open the ServiceHostBase to create listeners and start 
            // listening for messages.
            serviceHost.Open();
        }

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

    // Provide the ProjectInstaller class which allows 
    // the service to be installed by the Installutil.exe tool
    [RunInstaller(true)]
    public class ProjectInstaller : Installer
    {
        private ServiceProcessInstaller process;
        private ServiceInstaller service;

        public ProjectInstaller()
        {
            process = new ServiceProcessInstaller();
            process.Account = ServiceAccount.LocalSystem;
            service = new ServiceInstaller();
            service.ServiceName = "WCFWindowsServiceSample";
            Installers.Add(process);
            Installers.Add(service);
        }
    }
}

解决方案

In order for your GUI (client) application to be able to talk to the Windows service, you need to use an Inter-Process Communication mechanism, since both the Windows service and the GUI are standalone, independent processes. The easiest way is to create a NetNamedPipe using Windows Communication Foundation.

Part I: Windows Service

I'm assuming you already have created a Windows service and know how to deploy it. So we begin by adding a contract to the Windows service project called ICalculatorService (make sure this interface is in its own file):

[ServiceContract]
public interface ICalculatorService
{
    [OperationContract]
    void Add(double value);

    [OperationContract]
    List<double> GetAllNumbers();
}

Then, we need to implement this interface. Create a new class (again, in its own file) called CalculatorService:

public class CalculatorService: ICalculatorService
{
    private static List<double> m_myValues = new List<double>();

    public void Add(double value)
    {
        m_myValues.Add(value);
    }

    public List<double> GetAllNumbers()
    {
        return m_myValues;
    }
}

Notice that we have a static List<double> which holds all the values. Now, we need make the Windows service a host, so that the client (GUI) can connect to it. The code-behind for the Windows service looks like this:

partial class CalculatorWindowsService : ServiceBase
{
    public ServiceHost m_host;

    public CalculatorWindowsService()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        // If the host is still open, close it first.
        if (m_host != null)
        {
            m_host.Close();
        }

        // Create a new host
        m_host = new ServiceHost(typeof(CalculatorService), new Uri("net.pipe://localhost"));

        // Note: "MyServiceAddress" is an arbitrary name. You can change it to whatever you want.
        m_host.AddServiceEndpoint(typeof(ICalculatorService), new NetNamedPipeBinding(), "MyServiceAddress");

        m_host.Open();
    }

    protected override void OnStop()
    {
        // Close the host when the service stops
        if (m_host != null)
        {
            m_host.Close();
            m_host = null;
        }
    }
}

This is all we need for the on the Windows service side.

Part II: GUI (Client) First, we need to make sure we create a contract just like the one we created in the Windows service, so that the client can successfully make the service calls. To do this, simply copy the ICalculatorService interface to the the client application. Make sure you change the namespace so that it's consistent with other classes in the client. I created a simple Windows Forms program with two buttons: Add Value and Get All Values. The code behind for this form looks like this:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
    }

    private void AddValue_Click(object sender, EventArgs e)
    {
        using (ChannelFactory<ICalculatorService> facotry = new ChannelFactory<ICalculatorService>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/MyServiceAddress")))
        {
            ICalculatorService proxy = facotry.CreateChannel();

            // Generate a random number to send to the service
            Random rand = new Random();
            var value = rand.Next(3, 20);

            // Send the random value to Windows service
            proxy.Add(value);
        }
    }

    private void GetAllValues_Click(object sender, EventArgs e)
    {
        using (ChannelFactory<ICalculatorService> facotry = new ChannelFactory<ICalculatorService>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/MyServiceAddress")))
        {
            ICalculatorService proxy = facotry.CreateChannel();

            // Get all the numbers from the service
            var returnedResult = proxy.GetAllNumbers();

            // Display the values returned by the service
            MessageBox.Show(string.Join("\n", returnedResult));
        }
    }
}

Here's a snapshot of my files in the Windows service and WinForms projects to help you see where things are:

Edit You can change the m_myValues to public, and access it inside the CalculatorWindowsService class.

这篇关于如何使一个WCF接口,利用在服务中声明的变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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