using System; using System.Collections; using System.Collections.Generic; using System.Linq; using ln.logging; namespace ln.application.service { public class ServiceContainer : IEnumerable { public Application Application { get; } public ServiceContainerRPC RPC { get { if (rpc == null) rpc = new ServiceContainerRPC(this); return rpc; } } ServiceContainerRPC rpc; HashSet serviceDefinitions = new HashSet(); public ServiceContainer(Application application) { Application = application; } public void Add(ServiceDefinition serviceDefinition) { serviceDefinitions.Add(serviceDefinition); } public void Remove(ServiceDefinition serviceDefinition) { serviceDefinitions.Remove(serviceDefinition); } public ServiceDefinition this[string serviceClassName] { get { foreach (ServiceDefinition serviceDefinition in serviceDefinitions) { if (serviceDefinition.ServiceClassName.Equals(serviceClassName)) return serviceDefinition; } throw new KeyNotFoundException(); } } public ServiceDefinition this[string assemblyName,string serviceClassName] { get { foreach (ServiceDefinition serviceDefinition in serviceDefinitions) { if (serviceDefinition.ServiceClassName.Equals(serviceClassName) && Object.Equals(serviceDefinition.AssemblyName,assemblyName)) return serviceDefinition; } throw new KeyNotFoundException(); } } public ServiceDefinition this[Type serviceType] { get { return this[serviceType.Assembly.FullName,serviceType.FullName]; } } public void Start(ServiceDefinition serviceDefinition) { if (!serviceDefinitions.Contains(serviceDefinition)) throw new NotSupportedException("ServiceDefinition not known to ServiceContainer"); ServiceDefinition sd = this[serviceDefinition.AssemblyName, serviceDefinition.ServiceClassName]; sd.Start(this.Application); } public void Stop(ServiceDefinition serviceDefinition) { if (!serviceDefinitions.Contains(serviceDefinition)) throw new NotSupportedException("ServiceDefinition not known to ServiceContainer"); ServiceDefinition sd = this[serviceDefinition.AssemblyName, serviceDefinition.ServiceClassName]; foreach (ServiceDefinition service in serviceDefinitions) { if (service.IsAlive) { if (service.ServiceBase.DependingServiceTypes.Contains(sd.ServiceType)) { Logging.Log(LogLevel.INFO, "Stopping depending Service: {0}", service.ServiceClassName); Stop(service); } } } sd.Stop(); } public void Load(ServiceDefinition serviceDefinition) { if (!serviceDefinitions.Contains(serviceDefinition)) throw new NotSupportedException("ServiceDefinition not known to ServiceContainer"); ServiceDefinition sd = this[serviceDefinition.AssemblyName, serviceDefinition.ServiceClassName]; sd.Load(); } public void Unload(ServiceDefinition serviceDefinition) { if (!serviceDefinitions.Contains(serviceDefinition)) throw new NotSupportedException("ServiceDefinition not known to ServiceContainer"); ServiceDefinition sd = this[serviceDefinition.AssemblyName, serviceDefinition.ServiceClassName]; sd.Unload(); } public IEnumerator GetEnumerator() { return ((IEnumerable)serviceDefinitions).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)serviceDefinitions).GetEnumerator(); } public class ServiceContainerRPC { public ServiceContainer ServiceContainer { get; } public ServiceContainerRPC(ServiceContainer serviceContainer) { ServiceContainer = serviceContainer; } public String[] GetServiceNames() { return ServiceContainer.Select((x) => x.ServiceClassName).ToArray(); } public sServiceDefinition GetServiceDefinition(string serviceClass) { return new sServiceDefinition(ServiceContainer[serviceClass]); } } public struct sServiceDefinition { public String ServiceClassName; public bool IsLoaded; public bool IsAlive; public bool IsReady; public sServiceDefinition(ServiceDefinition serviceDefinition) { ServiceClassName = serviceDefinition.ServiceClassName; IsLoaded = serviceDefinition.IsLoaded; IsAlive = serviceDefinition.IsAlive; IsReady = serviceDefinition.ServiceBase != null ? serviceDefinition.ServiceBase.IsReady : false; } } } }