What is the proper way to Host dozens of WCF Services in a single Windows Service?
-
25-02-2021 - |
سؤال
I've been tasked with moving over dozens of WCF Services to a single Windows Service. I've created a Windows Service using the Windows Service template and added the the following code to ServiceHostController:
public partial class ServiceHostController : ServiceBase
{
private List<ServiceHost> serviceHosts;
public ServiceHostController()
{
InitializeComponent();
this.ServiceName = "WCFServices";
this.CanStop = true;
this.AutoLog = true;
}
protected override void OnStart(string[] args)
{
if (serviceHosts != null)
{
foreach (var service in serviceHosts)
{
service.Close();
}
}
InitializeServices();
foreach (var service in serviceHosts)
{
service.Open();
}
}
protected override void OnStop()
{
if (serviceHosts != null)
{
foreach (var service in serviceHosts)
{
service.Close();
}
serviceHosts.Close(); = null;
}
foreach (var service in serviceHosts)
{
service.Close();
}
}
private void InitializeServices()
{
serviceHosts = new List<ServiceHost>()
{
new ServiceHost(typeof(WCFService1)),
new ServiceHost(typeof(WCFService2)),
// add dozens of services here
};
}
}
Besides not following the Do not repeat yourself rule here (actual code is different), is this how I should be hosting these WCF services in the Windows Service code?
المحلول
Hans, you got everything right, But I will replace your InitializeServices(); with following code. It is pseudo code so you need to replace the bits :)
1) Configure your endpoints in app.config
2) Get your Service types from your Service project\assembly
Dictionary<Type, Type> mappings = new Dictionary<Type,Type>();
foreach (Type t in MyServiceAssembly.GetTypes())
{
if (t.GetInterfaces().Length > 0)
{
foreach (Type ti in t.GetInterfaces())
{
if (mapping.ContainsKey(ti))
System.Diagnostics.Debug.WriteLine("Class {0} implements more than one interface {1}", t.FullName, ti.FullName);
else
mapping.Add(ti, t);
// System.Diagnostics.Debug.WriteLine("Class {0} implements {1}", t.FullName, ti.FullName);
}
}
}
4) If you want control end points from app.config Now iterate over your end points and get corresponding service implementation then create your hosts
//read your endpoints in your service startup
List<ServiceHost> serviceHosts = new List<ServiceHost>();
ServicesSection servicesSection = (ServicesSection)WebConfigurationManager.GetSection("system.serviceModel/services");
for(int i = 0;i<servicesSection.Services.Count;i++)
{
ServiceEndpointElement endpoint = servicesSection.Services[i].Endpoints[0];
string url = string.Format("net.tcp://{0}:{1}/YouNameSpace_service_Name_From_EndPoint/{2}.svc","YourHost","YourPort");
ServiceHost serviceHost = new ServiceHost(mappings[endpoint.Contract] , new Uri(url));
serviceHost.Open();
mServiceHosts.Add(serviceHost);
}
5) If you do not want to control end points from app.config then iterate over your mapping list.
//do this in your service startup
List<ServiceHost> serviceHosts = new List<ServiceHost>();
foreach(type t in mappings.Keys)
{
string url = string.Format("net.tcp://{0}:{1}/YouNameSpace_{2}.svc","YourHost","YourPort",t.name);
ServiceHost serviceHost = new ServiceHost(mappings[t] , new Uri(url));
serviceHost.Open();
mServiceHosts.Add(serviceHost);
}