• Container


     internal struct CachedTypeInfo
        {
            public Type Type;
            public bool IsSingleton;
        }
    internal class ConstructorCache
        {
            private static ConcurrentDictionary<Type, ConstructorInfo> _constructorCache = new ConcurrentDictionary<Type, ConstructorInfo>();
    
            public static ConstructorInfo GetConstructor(Type type)
            {
                ConstructorInfo constructor;
    
                if (!_constructorCache.TryGetValue(type, out constructor))
                    constructor = _constructorCache[type] = DiscoverConstructor(type.GetTypeInfo());
    
                return constructor;
            }
            private static ConstructorInfo DiscoverConstructor(TypeInfo typeInfo)
            {
                var constructors = typeInfo.DeclaredConstructors;
    
                if (constructors.Any())
                    return constructors.First();
    
                return null;
            }
        }
     public interface IContainer : IServiceProvider
        {
            void Register<TService, TImplementation>() where TImplementation : TService;
            void Register<TService, TImplementation>(bool singleton) where TImplementation : TService;
            void Register<TService>(Type implementation, bool singleton);
            void Register<TService>(Type implementation, Action<TService> callback, bool singleton);
            void Register(Type service, Type implementation, bool singleton);
            void Register<TService>(TService instance);
            T Resolve<T>();
            bool IsRegistered<T>();
        }
    internal class ParameterCache
        {
            private static ConcurrentDictionary<ConstructorInfo, List<ParameterInfo>> _parameterCache = new ConcurrentDictionary<ConstructorInfo, List<ParameterInfo>>();
    
            public static List<ParameterInfo> GetParameters(ConstructorInfo constructor)
            {
                List<ParameterInfo> parameterInfo;
    
                if (!_parameterCache.TryGetValue(constructor, out parameterInfo))
                {
                    // Not in cache, discover and add to cache.
                    parameterInfo = _parameterCache[constructor] = DiscoverParameters(constructor);
                }
    
                return parameterInfo;
            }
            private static List<ParameterInfo> DiscoverParameters(ConstructorInfo constructor)
            {
                return constructor.GetParameters().ToList();
            }
        }
    public class SimpleContainer : IContainer
        {
            private readonly ConcurrentDictionary<Type, CachedTypeInfo> _serviceTypeLookup = new ConcurrentDictionary<Type, CachedTypeInfo>();
            private readonly ConcurrentDictionary<Type, object> _serviceInstanceLookup = new ConcurrentDictionary<Type, object>();
            private readonly ConcurrentDictionary<Type, Action<object>> _serviceTypeCallbackLookup = new ConcurrentDictionary<Type, Action<object>>();
    
            #region IContainer Implementation
    
            public void Register<TService, TImplementation>() where TImplementation : TService
            {
                _serviceTypeLookup[typeof(TService)] = new CachedTypeInfo { Type = typeof(TImplementation), IsSingleton = true };
            }
    
            public void Register<TService, TImplementation>(bool singleton = true) where TImplementation : TService
            {
                _serviceTypeLookup[typeof(TService)] = new CachedTypeInfo { Type = typeof(TImplementation), IsSingleton = singleton };
            }
    
            public void Register<TService>(Type implementationType, bool singleton = true)
            {
                if (implementationType == null)
                    throw new ArgumentNullException("implementationType cannot be null.");
    
                _serviceTypeLookup[typeof(TService)] = new CachedTypeInfo { Type = implementationType, IsSingleton = singleton };
            }
    
            public void Register<TService>(Type implementationType, Action<TService> callback, bool singleton = true)
            {
                if (implementationType == null)
                    throw new ArgumentNullException("serviceType cannot be null.");
    
                _serviceTypeLookup[typeof(TService)] = new CachedTypeInfo { Type = implementationType, IsSingleton = singleton };
    
                if (callback != null)
                    _serviceTypeCallbackLookup[typeof(TService)] = (x) => callback((TService)x);
            }
    
            public void Register(Type serviceType, Type implementationType, bool singleton = true)
            {
                if (serviceType == null)
                    throw new ArgumentNullException("serviceType cannot be null.");
    
                if (implementationType == null)
                    throw new ArgumentNullException("serviceType cannot be null.");
    
                if (!serviceType.IsAssignableFrom(implementationType))
                    throw new ArgumentException(string.Format("Service could not be registered. {0} does not implement {1}.", implementationType.Name, serviceType.Name));
    
                _serviceTypeLookup[serviceType] = new CachedTypeInfo { Type = implementationType, IsSingleton = singleton };
            }
    
            public void Register<TService>(TService instance)
            {
                if (instance == null)
                    throw new ArgumentNullException("instance cannot be null.");
    
                _serviceInstanceLookup[typeof(TService)] = instance;
            }
    
            public T Resolve<T>()
            {
                return (T)Resolve(typeof(T));
            }
    
            private object Resolve(Type type)
            {
                CachedTypeInfo containerType;
                object instance = null;
    
                // If the type isn't registered, register the type to itself.
                if (!_serviceTypeLookup.TryGetValue(type, out containerType))
                {
                    Register(type, type);
                    containerType = new CachedTypeInfo { Type = type, IsSingleton = true };
                }
    
                // TODO: Should it use the instance by default? I'd assume so initially.
                // Check if the service has an instance in the list of instances, if so, return it here.
                if (_serviceInstanceLookup.TryGetValue(type, out instance))
                    return instance;
    
                var constructor = ConstructorCache.GetConstructor(containerType.Type);
                if (constructor != null)
                {
                    // Get constructor parameters.
                    var parameters = ParameterCache.GetParameters(constructor);
                    var parameterObjects = new List<object>();
    
                    foreach (var parameter in parameters)
                    {
                        parameterObjects.Add(Resolve(parameter.ParameterType));
                    }
    
                    var obj = Activator.CreateInstance(containerType.Type, parameterObjects.ToArray());
    
                    Action<object> callback;
                    if (_serviceTypeCallbackLookup.TryGetValue(type, out callback))
                        callback(obj);
    
                    if (containerType.IsSingleton)
                        _serviceInstanceLookup[type] = obj;
    
                    return obj;
                }
                else
                {
                    // Return null rather than throw an exception for resolve failures.
                    // This null will happen when there are 0 constructors for the supplied type.
                    return null;
                }
            }
    
            public bool IsRegistered<TService>()
            {
                if (_serviceTypeLookup.ContainsKey(typeof(TService)) || _serviceInstanceLookup.ContainsKey(typeof(TService)))
                    return true;
    
                return false;
            }
    
            #endregion
    
            #region IServiceProvider Implementation
    
            public object GetService(Type serviceType)
            {
                return Resolve(serviceType);
            }
    
            #endregion
        }
    internal static class TypeResolver
        {
            private static ConcurrentDictionary<Type, Type> _typeCache = new ConcurrentDictionary<Type, Type>();
    
            public static Type Resolve<T>(string className)
            {
                var type = typeof(T);
                Type implementationType = null;
    
                if (!_typeCache.TryGetValue(type, out implementationType))
                {
                    implementationType =
                        _typeCache[type] = Resolve(className, type);
                }
    
                return implementationType;
            }
    
            public static Type Resolve(string implementingType, Type serviceType = null)
            {
                var assemblies = AppDomain.CurrentDomain.GetAssemblies();
                var types = assemblies.SelectMany(a => a.GetTypes());
    
                Type type = null;
    
                if (serviceType != null)
                    type = types.FirstOrDefault(t => t.Name == implementingType && serviceType.IsAssignableFrom(t));
                else
                    type = types.FirstOrDefault(t => t.Name == implementingType);
    
                return type;
            }
        }
  • 相关阅读:
    Android开发需要注意的地方
    Android开发 --微信支付开发(转载!)(开发工具:Eclipse)
    Android开发---支付宝功能接口(支付功能)(转载!)
    Android开发--推送
    ASP.NET如何发布更新
    如何用visual studio控件(repeater)绑定数据库(SQL server)信息并显示
    SQL Server 的远程连接(转载)
    设置如何自动备份数据库并删除2周前的自动备份数据
    如何禁止网页内容被复制以及如何解除禁止(转载并更新!)
    条码生成
  • 原文地址:https://www.cnblogs.com/RR-ghost/p/9765988.html
Copyright © 2020-2023  润新知