|
|
|
|
Start ServiceHosts for all configured Services
|
Important Update: The originally presented code only works if the service is defined in the same assembly which hosts the service (because the name="" attribute in <service> may not contain the assembly name of the service). See at the end of the article for a slightly different version which works in all cases --- but which involves adding a second config file.
As WCF has reached RC1 stage, I find myself cleaning up a few bits of older WCF code. While playing around with it, I always found myself having to start more and more ServiceHosts for different configurations. The following snippet iterates over all <service> entries in configuration/system.serviceModel and opens a ServiceHost for each of them.
Update: Added code to close all services.
using System; using System.Collections.Generic; using System.Reflection; using System.Configuration; using System.ServiceModel.Configuration; using System.ServiceModel;
public class ServiceHostGroup { static List<ServiceHost> _hosts = new List<ServiceHost>();
private static void OpenHost(Type t) { ServiceHost hst = new ServiceHost(t); hst.Open(); _hosts.Add(hst); }
public static void StartAllConfiguredServices() { Configuration conf = ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location);
ServiceModelSectionGroup svcmod = (ServiceModelSectionGroup)conf.GetSectionGroup("system.serviceModel"); foreach (ServiceElement el in svcmod.Services.Services) { Type svcType = Type.GetType(el.Name); if (svcType == null) throw new Exception("Invalid Service Type " + el.Name + " in configuration file."); OpenHost(svcType); }
}
public static void CloseAllServices() { foreach (ServiceHost hst in _hosts) { hst.Close(); } } }
As mentioned above, I have in the meantime learned (after long and hard fighting against the "this service has no non-metadata endpoints"-exception), that the name="" attribute in <service> must not contain an assembly name. I guess I have been too used to Remoting configuration files after all ;-). To still get dynamic service configuration without code changes, I've added a second configuration file called services.xml and changed the code for ServiceHostGroup to the following:
Services.XML:
<configuredServices> <service type="ServiceImplementation.ArticleService, ServiceImplementation" /> </configuredServices>
ServiceHostBase.cs:
using System; using System.Collections.Generic; using System.Reflection; using System.Configuration; using System.ServiceModel.Configuration; using System.ServiceModel; using System.Xml; using System.Xml.Serialization; using System.IO;
public class ServiceHostGroup { static List<ServiceHost> _hosts = new List<ServiceHost>();
private static void OpenHost(Type t) { ServiceHost hst = new ServiceHost(t); Type ty = hst.Description.ServiceType; hst.Open(); _hosts.Add(hst); }
public static void StartAllConfiguredServices() { ConfiguredServices services = ConfiguredServices.LoadFromFile("services.xml");
foreach (ConfiguredService svc in services.Services) { Type svcType = Type.GetType(svc.Type); if (svcType == null) throw new Exception("Invalid Service Type " + svc.Type + " in configuration file."); OpenHost(svcType); } }
public static void CloseAllServices() { foreach (ServiceHost hst in _hosts) { hst.Close(); } } }
[XmlRoot("configuredServices")] public class ConfiguredServices { public static ConfiguredServices LoadFromFile(string filename) { if (!File.Exists(filename)) return new ConfiguredServices();
XmlSerializer ser = new XmlSerializer(typeof(ConfiguredServices)); using (FileStream fs = File.OpenRead(filename)) { return (ConfiguredServices) ser.Deserialize(fs); } }
[XmlElement("service", typeof(ConfiguredService))] public List<ConfiguredService> Services = new List<ConfiguredService>(); }
public class ConfiguredService { [XmlAttribute("type")] public string Type; }
|
© 2002 - 2006 by thinktecture, Ingo Rammer and Christian Weyer. All rights reserved.

|
|