using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Reflection; namespace OpenSEMI.Core.Container { public class w : IContainer, IServiceProvider { private readonly ConcurrentDictionary _serviceTypeLookup = new ConcurrentDictionary(); private readonly ConcurrentDictionary _serviceInstanceLookup = new ConcurrentDictionary(); private readonly ConcurrentDictionary> _serviceTypeCallbackLookup = new ConcurrentDictionary>(); public void Register() where TImplementation : TService { _serviceTypeLookup[typeof(TService)] = new CachedTypeInfo { Type = typeof(TImplementation), IsSingleton = true }; } public void Register(bool singleton = true) where TImplementation : TService { _serviceTypeLookup[typeof(TService)] = new CachedTypeInfo { Type = typeof(TImplementation), IsSingleton = singleton }; } public void Register(Type implementationType, bool singleton = true) { if (implementationType == (Type)null) { throw new ArgumentNullException("implementationType cannot be null."); } _serviceTypeLookup[typeof(TService)] = new CachedTypeInfo { Type = implementationType, IsSingleton = singleton }; } public void Register(Type implementationType, Action callback, bool singleton = true) { if (implementationType == (Type)null) { throw new ArgumentNullException("serviceType cannot be null."); } _serviceTypeLookup[typeof(TService)] = new CachedTypeInfo { Type = implementationType, IsSingleton = singleton }; if (callback != null) { _serviceTypeCallbackLookup[typeof(TService)] = delegate(object x) { callback((TService)x); }; } } public void Register(Type serviceType, Type implementationType, bool singleton = true) { if (serviceType == (Type)null) { throw new ArgumentNullException("serviceType cannot be null."); } if (implementationType == (Type)null) { throw new ArgumentNullException("serviceType cannot be null."); } if (!serviceType.IsAssignableFrom(implementationType)) { throw new ArgumentException($"Service could not be registered. {implementationType.Name} does not implement {serviceType.Name}."); } _serviceTypeLookup[serviceType] = new CachedTypeInfo { Type = implementationType, IsSingleton = singleton }; } public void Register(TService instance) { if (instance == null) { throw new ArgumentNullException("instance cannot be null."); } _serviceInstanceLookup[typeof(TService)] = instance; } public T Resolve() { return (T)Resolve(typeof(T)); } private object Resolve(Type type) { object value = null; if (!_serviceTypeLookup.TryGetValue(type, out CachedTypeInfo value2)) { Register(type, type, true); CachedTypeInfo cachedTypeInfo = default(CachedTypeInfo); cachedTypeInfo.Type = type; cachedTypeInfo.IsSingleton = true; value2 = cachedTypeInfo; } if (_serviceInstanceLookup.TryGetValue(type, out value)) { return value; } ConstructorInfo constructor = ConstructorCache.GetConstructor(value2.Type); if (constructor != (ConstructorInfo)null) { List parameters = ParameterCache.GetParameters(constructor); List list = new List(); foreach (ParameterInfo item in parameters) { list.Add(Resolve(item.ParameterType)); } object obj = Activator.CreateInstance(value2.Type, list.ToArray()); if (_serviceTypeCallbackLookup.TryGetValue(type, out Action value3)) { value3(obj); } if (value2.IsSingleton) { _serviceInstanceLookup[type] = obj; } return obj; } return null; } public bool IsRegistered() { if (_serviceTypeLookup.ContainsKey(typeof(TService)) || _serviceInstanceLookup.ContainsKey(typeof(TService))) { return true; } return false; } public object GetService(Type serviceType) { return Resolve(serviceType); } } }