WCF 服务的host方式主要有两种:self-hosting,active-hosting,举个例子:前者是指将wcf service 寄宿到console application上,后者则是将wcf service部署到IIS上。至于它们的好处嘛,感觉还是根据具体的需求来选择具体的途径。
WCF service 在host之前,是可以对它进行一些修改,比如:添加behavior,endpoint。这些修改主要是用来修改Service Description类,因为service 在host的时候是需要根据该类来构建一系列的对象。
贴一段关于service description的代码
var serviceDescription = CreateServiceDescription();
Console.WriteLine("{0, -17}: {1}", "Name", serviceDescription.Name);
Console.WriteLine("{0, -17}: {1}", "Namespace", serviceDescription.Namespace);
Console.WriteLine("{0, -17}: {1}", "ConfigurationName", serviceDescription.ConfigurationName);
Console.WriteLine("{0, -17}: {1}", "Behaviors", serviceDescription.Behaviors[0].GetType().Name);
for (int i = 1; i < serviceDescription.Behaviors.Count; i++)
{
Console.WriteLine("{0, -17}: {1}", "", serviceDescription.Behaviors[i].GetType().Name);
}
Console.WriteLine();
for (int i = 1; i <= serviceDescription.Endpoints.Count; i++)
{
ServiceEndpoint endpoint = serviceDescription.Endpoints[i - 1];
Console.WriteLine("第{0}个终结点", i);
Console.WriteLine("\t{0, -9}: {1}", "Address", endpoint.Address);
Console.WriteLine("\t{0, -9}: {1}", "Binding", endpoint.Binding);
Console.WriteLine("\t{0, -9}: {1}", "Contract", endpoint.Contract.ContractType.Name);
if (endpoint.Behaviors.Count > 0)
{
Console.WriteLine("\t{0, -9}: {1}", "Behaviors", endpoint.Behaviors[0].GetType().Name);
}
for (int j = 1; j < endpoint.Behaviors.Count; j++)
{
Console.WriteLine("\t{0, -9}: {1}", "", endpoint.Behaviors[j].GetType().Name);
}
Console.WriteLine();
}
static ServiceDescription CreateServiceDescription()
{
Type serviceType=typeof(CalculatorService);
ServiceDescription description = new ServiceDescription();
description.ServiceType = serviceType;
var serviceBehaviors=(from item in serviceType.GetCustomAttributes(false)
where item is IServiceBehavior
select item as IServiceBehavior).ToArray();
Array.ForEach(serviceBehaviors,(item)=>{description.Behaviors.Add(item);});
if(description.Behaviors.Find<ServiceBehaviorAttribute>() ==null)
{
ServiceBehaviorAttribute behavior=new ServiceBehaviorAttribute();
description.Behaviors.Add(behavior);
}
description.Name=description.Behaviors.Find<ServiceBehaviorAttribute>().Name;
description.Namespace=description.Behaviors.Find<ServiceBehaviorAttribute>().Namespace;
description.ConfigurationName = description.Behaviors.Find<ServiceBehaviorAttribute>().ConfigurationName;
//load service behaviors from configuration file
ServiceElement serviceElement = ConfigLoader.GetServiceElement(description.ConfigurationName);
if (!string.IsNullOrEmpty(serviceElement.BehaviorConfiguration))
{
ServiceBehaviorElement behaviorElement = ConfigLoader.GetServiceBehaviorElement(serviceElement.BehaviorConfiguration);
foreach (BehaviorExtensionElement extensionElemenet in behaviorElement)
{
IServiceBehavior serviceBehavior = extensionElemenet.CreateBehavior() as IServiceBehavior;
description.Behaviors.Add(serviceBehavior);
}
}
//add EndpointAdress from configuraiton file
foreach (ServiceEndpointElement endpointElement in serviceElement.Endpoints)
{
description.Endpoints.Add(CreateServiceEndpoint(serviceType,endpointElement));
}
return description;
}
wcf service 在host的时候有2种方式来生成必须的绑定元素,1)根据配置文件生产;2)动态绑定。贴两段关于动态生成Service Endpoint 和 Service Contract 的代码:
static ServiceEndpoint CreateServiceEndpoint(Type serviceType, ServiceEndpointElement endpointElement)
{
//创建ServiceEndpoint
EndpointAddress address = new EndpointAddress(endpointElement.Address);
Binding binding = ConfigLoader.CreateBinding(endpointElement.Binding);
ContractDescription contract = CreateContractDescription(serviceType, endpointElement.Contract);
ServiceEndpoint endpoint = new ServiceEndpoint(contract, binding, address);
//添加终结点行为
if (!string.IsNullOrEmpty(endpointElement.BehaviorConfiguration))
{
EndpointBehaviorElement behaviorElement = ConfigLoader.GetEndpointBehaviorElement(endpointElement.BehaviorConfiguration);
foreach (BehaviorExtensionElement extensionElement in behaviorElement)
{
IEndpointBehavior endpointBehavior = (IEndpointBehavior)extensionElement.CreateBehavior();
endpoint.Behaviors.Add(endpointBehavior);
}
}
return endpoint;
}
static ContractDescription CreateContractDescription(Type serviceType, string configurationName)
{
foreach (Type contract in serviceType.GetInterfaces())
{
ServiceContractAttribute serviceContractAttribute = contract.GetCustomAttributes(typeof(ServiceContractAttribute), false).FirstOrDefault() as ServiceContractAttribute;
if (null != serviceContractAttribute)
{
string configName = serviceContractAttribute.ConfigurationName ?? contract.Namespace + "." + contract.Name;
if (configurationName == configName)
{
return ContractDescription.GetContract(contract, serviceType);
}
}
}
return null;
}
}
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;
behavior.HttpGetUrl = new Uri(host.Description.Endpoints[0].Address.Uri.ToString() + "/mex");
host.Description.Behaviors.Add(behavior);
host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), host.Description.Endpoints[0].Address.Uri.ToString() + "/mex");
关于SVC文件的Factory属性,如果我们想在激活host在svc文件中的wcf时加入些自定义逻辑,我们可以为factory属性指定一个继承servicefactoryhostbase的类,该类的首个参数为service属性。