WCF学习(2) ServiceHost寄宿多个服务

时间:2022-06-24 02:16:47

WCF学习(2) ServiceHost寄宿多个服务

WCF在实际应用中,通常都会寄宿多个服务。网上的做法通常有2种:
1. 将服务协定实现在一个类里面,利用partial将实现分散到多个文件,然后添加多个终结点,只需要开启一个ServiceHost.
2. 每个服务开启一个ServiceHost,这种做法在实际实现上也会有所不同,比如可以需要调用某个服务的时候再去开启,利用线程锁来控制同时开启的服务数,或者一次开启所有的服务.


实例1.将服务协定实现在一个类里面,然后添加多个终结点

  • 服务协定
[ServiceContract]
public interface IUserService
{
[OperationContract]
string UpdateUser(string json);

[OperationContract]
string UpdateUserList(string json);

[OperationContract]
string GetAllUser(string json);

[OperationContract]
string GetUserByName(string json);

[OperationContract]
string AddUser(string json);

[OperationContract]
string AddUserList(string json);

[OperationContract]
string DeleteUser(string json);
}

省略了ISysConfigService

  • 服务实现

WCF学习(2) ServiceHost寄宿多个服务
省略了SysConfigService

  • 服务端启动WCF服务代码
try
{
    NetTcpBinding bind = new NetTcpBinding();
    bind.Security.Mode = SecurityMode.None;
    bind.MaxReceivedMessageSize = 2147483647;
    Uri baseAddress = new Uri(string.Format("net.tcp://{0}:{1}/Service", HostIP, 8000));

    if (host == null)
        host = new ServiceHost(typeof(ServiceImp), baseAddress);

    host.AddServiceEndpoint(typeof(ISysConfigService), bind, "SysConfigService");
    host.AddServiceEndpoint(typeof(IUserService), bind, "UserService");

    if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
    {
        ServiceMetadataBehavior sb = new ServiceMetadataBehavior();
        sb.HttpGetEnabled = true;
        sb.HttpGetUrl = new Uri("http://127.0.0.1:80/Service");
        host.Description.Behaviors.Add(sb);
        //host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
    }

    if (host.State != CommunicationState.Opened)
    {
        host.Opened += delegate
        {
            Console.WriteLine("WCF服务已启动,地址:{0}", string.Format("Address:{0}", baseAddress.AbsoluteUri));
            foreach (ServiceEndpoint se in host.Description.Endpoints)
            {
                Console.WriteLine("[终结点]: {0}\r\n\t[A-地址]: {1} \r\n\t [B-绑定]: {2} \r\n\t [C-协定]: {3}",
             se.Name, se.Address, se.Binding.Name, se.Contract.Name);
            }
        };
        host.Open();
    }
}
catch (Exception ex)
{
    throw ex;
}
  • 客户端
EndpointAddress address = new EndpointAddress("net.tcp://127.0.0.1:8000/Service/SysConfigService");
NetTcpBinding bind = new NetTcpBinding();
bind.Security.Mode = SecurityMode.None;
bind.MaxReceivedMessageSize = 2147483647;

var factoy = new ChannelFactory<ISysConfigService>(bind, address);
var channel = factoy.CreateChannel();
var ret = channel.GetAllClientConfig("");
Console.WriteLine(ret);

Console.ReadKey();
factoy.Close();

实例2.开启多个ServiceHost

服务协定和实现见前面

  • 服务端代码
    利用反射来获取服务协定
try
{
    #region 根据XMl添加服务终结点
    var sourceAssembly = System.Reflection.Assembly.GetExecutingAssembly();
    var resourceNames = sourceAssembly.GetManifestResourceNames();
    string currDBVersionPath = string.Format("{0}.{1}", sourceAssembly.GetName().Name, "Services.xml");
    var stream = sourceAssembly.GetManifestResourceStream(currDBVersionPath);
    XElement root = XElement.Load(stream);
    if (root != null)
    {
        IDictionary<string, string> objectDefine = new Dictionary<string, string>();

        var objects = from obj in root.Descendants()
                      where obj.Attribute("isactive").Value == "1"
                      select obj;
        objectDefine = objects.ToDictionary(
                k => k.Attribute("address").Value,
                v =>
                {
                    return v.Attribute("namespace").Value;
                }
            );

        foreach (var item in objectDefine)
        {
            System.Reflection.Assembly AsbmContract = System.Reflection.Assembly.Load("ConfigServer");
            if (AsbmContract == null)
            {
                throw new ArgumentException("获取ConfigServerl程序集信息为空.");
            }
            if (string.IsNullOrEmpty(item.Value))
            {
                CommHelper.LogHelper4net.LogInfo(CommHelper.Log4NetType.Info, "Server->HostOpen", string.Format("终节点信息为空:{0}", item.Value));
                continue;
            }
            Type supType = AsbmContract.GetType(item.Value, false, true);
            if (supType == null)
            {
                CommHelper.LogHelper4net.LogInfo(CommHelper.Log4NetType.Info, "Server->HostOpen", string.Format("终节点信息为空:{0}", item.Value));
                continue;
            }
            string address = item.Key;

            Uri baseAddress = new Uri(string.Format("net.tcp://{0}:{1}/Service", "127.0.0.1", 8000));
            NetTcpBinding bind = new NetTcpBinding();
            bind.Security.Mode = SecurityMode.None;
            bind.MaxReceivedMessageSize = 2147483647; 
            ServiceHost host=new ServiceHost(typeof(ServiceImp), baseAddress); //如果不是多个服务协定实现到一个类,可以取具体的类来实例化
            ServiceMetadataBehavior sb = new ServiceMetadataBehavior();
            sb.HttpGetEnabled = true;
            sb.HttpGetUrl = new Uri("http://127.0.0.1:80/Service/"+address);
            host.Description.Behaviors.Add(sb);
            //host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");

            host.AddServiceEndpoint(supType, bind, address);
            if (host.State != CommunicationState.Opened)
            {
                host.Opened += delegate
                {
                    Console.WriteLine("WCF服务已启动,地址:{0}", string.Format("Address:{0}", baseAddress.AbsoluteUri));
                    foreach (ServiceEndpoint se in host.Description.Endpoints)
                    {
                        Console.WriteLine("[终结点]: {0}\r\n\t[A-地址]: {1} \r\n\t [B-绑定]: {2} \r\n\t [C-协定]: {3}",
                     se.Name, se.Address, se.Binding.Name, se.Contract.Name);
                    }
                };
                host.Open();
            }
        }
    }
    #endregion
}
catch (Exception ex)
{
    throw ex;
}
  • Services.xml的内容
<?xml version="1.0" encoding="utf-8" ?>
<Services>
  <!--<service type="ServiceImplementation.ArticleService, ServiceImplementation" />-->
  <service id="1" namespace="ConfigServer.ISysConfigService" address="SysConfigService" isactive="1"></service>
  <service id="2" namespace="ConfigServer.IUserService" address="UserService" isactive="1"></service>
</Services>