123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- namespace Wayne.Lib
- {
- class ServiceContainer : IServiceContainer
- {
- private readonly IServiceLocator parentServiceLocator;
- private readonly Dictionary<ServiceKey, object> services;
- private bool disposed;
- private List<Func<Type, object>> resolvers = new List<Func<Type, object>>();
- public ServiceContainer()
- : this(null)
- {
- }
- public ServiceContainer(IServiceLocator parentServiceLocator)
- {
- services = new Dictionary<ServiceKey, object>();
- this.parentServiceLocator = parentServiceLocator;
- }
- public void RegisterResolver(Func<Type, object> requestedType)
- {
- resolvers.Add(requestedType);
- }
- public void RegisterService<TServiceImplementation>()
- {
- AssertContainerIsNotDisposed();
- var instance = (TServiceImplementation)TryCreate(typeof(TServiceImplementation));
- RegisterService(instance);
- }
- public void RegisterService<TServiceImplementation>(string serviceId)
- {
- AssertContainerIsNotDisposed();
- var instance = (TServiceImplementation)TryCreate(typeof(TServiceImplementation), serviceId);
- RegisterService(instance, serviceId);
- }
- public void RegisterService<TServiceContract>(TServiceContract serviceInstance)
- {
- RegisterService(serviceInstance, string.Empty);
- }
- public void RegisterService<TServiceContract>(TServiceContract serviceInstance, string serviceId)
- {
- AssertContainerIsNotDisposed();
- services[new ServiceKey(typeof(TServiceContract), serviceId)] = serviceInstance;
- }
- public void RegisterService<TServiceContract>(ObjectConstructor<IServiceLocator, TServiceContract> constructorMethod)
- {
- AssertContainerIsNotDisposed();
- var serviceInstance = constructorMethod.Invoke(this);
- services[new ServiceKey(typeof(TServiceContract))] = serviceInstance;
- }
- public void RegisterService<TServiceContract>(ObjectConstructor<IServiceLocator, TServiceContract> constructorMethod, string serviceId)
- {
- AssertContainerIsNotDisposed();
- var serviceInstance = constructorMethod.Invoke(this);
- services[new ServiceKey(typeof(TServiceContract), serviceId)] = serviceInstance;
- }
- public void RegisterService<TServiceContract, TServiceImplementation>()
- where TServiceImplementation : TServiceContract
- where TServiceContract : class
- {
- AssertContainerIsNotDisposed();
- var instance = (TServiceImplementation)TryCreate(typeof(TServiceImplementation));
- if ((object)instance == null)
- throw new ServiceContainerException(typeof(TServiceImplementation), "Could not create implementation");
- RegisterService<TServiceContract>(instance);
- }
- public void RegisterService<TServiceContract, TServiceImplementation>(string serviceId)
- where TServiceImplementation : TServiceContract
- where TServiceContract : class
- {
- AssertContainerIsNotDisposed();
- var instance = (TServiceImplementation)TryCreate(typeof(TServiceImplementation), serviceId);
- if ((object)instance == null)
- throw new ServiceContainerException(typeof(TServiceImplementation), "Could not create implementation");
- RegisterService<TServiceContract>(instance, serviceId);
- }
- public TServiceContract GetService<TServiceContract>()
- {
- return (TServiceContract)GetService(typeof(TServiceContract));
- }
- public TServiceContract GetService<TServiceContract>(string serviceId)
- {
- return (TServiceContract)GetService(typeof(TServiceContract), serviceId);
- }
- public object GetService(Type serviceType)
- {
- return GetService(serviceType, string.Empty);
- }
- public object GetService(Type serviceType, string serviceId)
- {
- AssertContainerIsNotDisposed();
- object service;
- if (services.TryGetValue(new ServiceKey(serviceType, serviceId), out service))
- return service;
-
- service = resolvers
- .Select(x => x(serviceType))
- .FirstOrDefault(x => x != null);
- if (service != null)
- return service;
-
- if (parentServiceLocator != null)
- return parentServiceLocator.GetService(serviceType, serviceId);
- throw ServiceContainerException.CreateNotFoundException(serviceType);
- }
- public TServiceContract GetServiceOrDefault<TServiceContract>(CreateDefaultService<TServiceContract> func, string serviceId)
- {
- AssertContainerIsNotDisposed();
- object service;
- Type serviceType = typeof(TServiceContract);
- var key = new ServiceKey(serviceType, serviceId);
- if (!services.TryGetValue(key, out service))
- {
-
- service = resolvers
- .Select(x => x(serviceType))
- .FirstOrDefault(x => x != null);
- if (service != null)
- {
- return (TServiceContract)service;
- }
- if (parentServiceLocator != null)
- return parentServiceLocator.GetServiceOrDefault(func, serviceId);
- return func();
- }
- return (TServiceContract)service;
- }
- public TServiceContract GetServiceOrDefault<TServiceContract>(CreateDefaultService<TServiceContract> func)
- {
- return GetServiceOrDefault(func, string.Empty);
- }
- public T CreateInstance<T>(params object[] additionalObjects) where T : class
- {
- return (T)CreateInstance(typeof(T), additionalObjects);
- }
- public object CreateInstance(Type typeToInstantiate, params object[] additionalParameter)
- {
- AssertContainerIsNotDisposed();
- object result = TryCreate(typeToInstantiate, additionalParameter);
- if (result == null)
- throw new ServiceContainerException(typeToInstantiate, "Could not create object");
- return result;
- }
- public T CreateInstance<T>(string serviceId, params object[] additionalObjects) where T : class
- {
- return (T)CreateInstance(typeof(T), serviceId, additionalObjects);
- }
- public object CreateInstance(Type typeToInstantiate, string serviceId, params object[] additionalParameter)
- {
- AssertContainerIsNotDisposed();
- object result = TryCreate(typeToInstantiate, serviceId, additionalParameter);
- if (result == null)
- throw new ServiceContainerException(typeToInstantiate, "Could not create object");
- return result;
- }
- private void AssertContainerIsNotDisposed()
- {
- if (disposed)
- throw new ObjectDisposedException(GetType().Name);
- }
- public object TryGetService(Type serviceType)
- {
- return TryGetService(serviceType, string.Empty);
- }
- public object TryGetService(Type serviceType, string serviceId)
- {
- object service;
- if (serviceType == typeof(IServiceLocator) || serviceType == typeof(IServiceContainer))
- return this;
- if (!services.TryGetValue(new ServiceKey(serviceType, serviceId), out service))
- {
-
- service = resolvers
- .Select(x => x(serviceType))
- .FirstOrDefault(x => x != null);
- if (service != null)
- {
- return service;
- }
- if (parentServiceLocator != null)
- return parentServiceLocator.TryGetService(serviceType, serviceId);
- return null;
- }
- return service;
- }
- public T TryGetService<T>()
- {
- return TryGetService<T>(string.Empty);
- }
- public T TryGetService<T>(string serviceId)
- {
- Type serviceType = typeof(T);
- object result;
- if (serviceType == typeof(IServiceLocator) || serviceType == typeof(IServiceContainer))
- result = this;
- else
- {
- if (!services.TryGetValue(new ServiceKey(serviceType, serviceId), out result))
- {
-
- result= resolvers
- .Select(x => x(serviceType))
- .FirstOrDefault(x => x != null);
- if (result != null)
- {
- return (T) result;
- }
- if (parentServiceLocator != null)
- result = parentServiceLocator.TryGetService(serviceType, serviceId);
- }
- }
- return (T)result;
- }
- private object TryCreate(Type typeToCreate, params object[] additionalObjects)
- {
- return TryCreate(typeToCreate, string.Empty, additionalObjects);
- }
- private object TryCreate(Type typeToCreate, string serviceId, params object[] additionalObjects)
- {
- var constructors = typeToCreate.GetConstructors();
- Array.Reverse(constructors);
- List<object> parameters = new List<object>();
- ConstructorInfo foundConstructor = null;
- foreach (ConstructorInfo constructor in constructors)
- {
- var parameterInfos = constructor.GetParameters();
- parameters.Clear();
- foreach (var parameterInfo in parameterInfos)
- {
- var dependency = TryGetService(parameterInfo.ParameterType, serviceId);
- if (dependency != null)
- {
- parameters.Add(dependency);
- }
- else
- {
- int firstMatchingParameterObjectIndex = -1;
- for (int index = 0; index < additionalObjects.Length; index++)
- {
- object additionalObject = additionalObjects[index];
- if (parameterInfo.ParameterType.IsAssignableFrom(additionalObject.GetType()))
- {
- firstMatchingParameterObjectIndex = index;
- break;
- }
- }
- if (firstMatchingParameterObjectIndex >= 0)
- {
- parameters.Add(additionalObjects[firstMatchingParameterObjectIndex]);
- }
- }
- }
- if (parameters.Count == parameterInfos.Length)
- {
- foundConstructor = constructor;
- break;
- }
- }
- if (foundConstructor != null)
- {
- var stateObject = foundConstructor.Invoke(parameters.ToArray());
- return stateObject;
- }
- return null;
- }
-
- private struct ServiceKey
- {
- private readonly Type _typeOfObject;
- private readonly string _id;
- public ServiceKey(Type typeOfObject, string id)
- {
- _typeOfObject = typeOfObject;
- _id = id;
- }
- public ServiceKey(Type typeOfObject)
- {
- _typeOfObject = typeOfObject;
- _id = string.Empty;
- }
- public override int GetHashCode()
- {
- int hash = 17;
- hash = hash * 31 + _typeOfObject.GetHashCode();
- hash = hash * 31 + _id.GetHashCode();
- return hash;
- }
- public override bool Equals(object obj)
- {
- return obj is ServiceKey && this == (ServiceKey)obj;
- }
- public static bool operator ==(ServiceKey s1, ServiceKey s2)
- {
- return (s1._typeOfObject == s2._typeOfObject) && (s1._id.Equals(s2._id, StringComparison.InvariantCulture));
- }
- public static bool operator !=(ServiceKey s1, ServiceKey s2)
- {
- return !(s1 == s2);
- }
- }
- #region Implementation of IDisposable
- ~ServiceContainer()
- {
- Dispose(false);
- }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- private void Dispose(bool disposing)
- {
- if (disposed) return;
- disposed = true;
- if (disposing)
- {
- foreach (var service in services.Values)
- {
- var disposable = service as IDisposable;
- if (disposable != null)
- {
- try
- {
- disposable.Dispose();
- }
- catch
- {
-
- }
- }
- }
- services.Clear();
- }
- }
- #endregion
- }
- }
|