ln.application/service/ServiceDefinition.cs

122 lines
4.4 KiB
C#

using System;
using System.Reflection;
using ln.logging;
using System.IO;
using System.Linq;
namespace ln.application.service
{
public class ServiceDefinition
{
public String AssemblyName { get; }
public String ServiceClassName { get; }
public bool AutoStart { get; set; }
public ApplicationServiceBase ServiceBase { get; private set; }
public bool IsLoaded => ServiceBase != null;
public bool IsAlive => IsLoaded && ServiceBase.IsAlive;
public Type ServiceType => serviceType;
Assembly serviceAssembly;
Type serviceType;
public ServiceDefinition(String assemblyName, string serviceClassName)
{
AssemblyName = assemblyName;
ServiceClassName = serviceClassName;
}
public ServiceDefinition(string serviceClassName)
{
AssemblyName = null;
ServiceClassName = serviceClassName;
}
public static ServiceDefinition From<S>() => From<S>(true);
public static ServiceDefinition From<S>(bool autoStart)
{
Type st = typeof(S);
ServiceDefinition sd = new ServiceDefinition(
st.Assembly.FullName,
st.FullName
);
sd.AutoStart = autoStart;
return sd;
}
public void Load()
{
if (IsLoaded)
throw new NotSupportedException(String.Format("Service {0} [{1}] is already loaded",ServiceClassName,AssemblyName));
if (AssemblyName != null)
serviceAssembly = Assembly.Load(AssemblyName);
serviceType = FinalAssembly.GetType(ServiceClassName);
if (serviceType == null)
throw new EntryPointNotFoundException(String.Format("could not get type {0}",ServiceClassName));
if (!serviceType.IsSubclassOf(typeof(ApplicationServiceBase)))
throw new NotSupportedException(String.Format("application service type must derive from ApplicationServiceBase"));
ServiceBase = (ApplicationServiceBase)Activator.CreateInstance(serviceType);
}
public void Unload() => Unload(false);
public void Unload(bool force)
{
if (!IsLoaded)
throw new NotSupportedException(String.Format("Service {0} [{1}] is not loaded", ServiceClassName, AssemblyName));
if (!force && IsAlive)
throw new NotSupportedException(String.Format("Service {0} [{1}] still alive", ServiceClassName, AssemblyName));
ServiceBase.Dispose();
ServiceBase = null;
serviceType = null;
serviceAssembly = null;
}
public void Start(Application application)
{
if (!IsLoaded)
Load();
Logging.Log(LogLevel.INFO, "service: starting {0} [{1}]", ServiceClassName, FinalAssembly.GetName().Name);
if (ServiceBase.Start(application,new string[0]))
Logging.Log(LogLevel.INFO, "service: started {0} [{1}]", ServiceClassName, FinalAssembly.GetName().Name);
else
Logging.Log(LogLevel.ERROR, "service: failed {0} [{1}]", ServiceClassName, FinalAssembly.GetName().Name);
}
public void Stop()
{
if (IsAlive)
{
Logging.Log(LogLevel.INFO, "service: stopping {0} [{1}]", ServiceClassName, FinalAssembly.GetName().Name);
if (ServiceBase.Stop())
Logging.Log(LogLevel.INFO, "service: stopped {0} [{1}]", ServiceClassName, FinalAssembly.GetName().Name);
else
Logging.Log(LogLevel.ERROR, "service: stopfail {0} [{1}]", ServiceClassName, FinalAssembly.GetName().Name);
}
}
private Assembly FinalAssembly => serviceAssembly != null ? serviceAssembly : Assembly.GetEntryAssembly();
public override int GetHashCode()
{
return (AssemblyName != null ? AssemblyName.GetHashCode() : 0) ^ ServiceClassName.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is ServiceDefinition)
{
ServiceDefinition other = obj as ServiceDefinition;
return Object.Equals(AssemblyName, other.AssemblyName) && ServiceClassName.Equals(other.ServiceClassName);
}
return false;
}
}
}