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
- 服务实现
省略了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>