private ServiceCallSite TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot) { if (serviceType == descriptor.ServiceType) { ServiceCacheKey callSiteKey = new ServiceCacheKey(serviceType, slot); if (_callSiteCache.TryGetValue(callSiteKey, out ServiceCallSite serviceCallSite)) { return(serviceCallSite); } ServiceCallSite callSite; var lifetime = new ResultCache(descriptor.Lifetime, serviceType, slot); if (descriptor.ImplementationInstance != null) { callSite = new ConstantCallSite(descriptor.ServiceType, descriptor.ImplementationInstance); } else if (descriptor.ImplementationFactory != null) { callSite = new FactoryCallSite(lifetime, descriptor.ServiceType, descriptor.ImplementationFactory); } else if (descriptor.ImplementationType != null) { callSite = CreateConstructorCallSite(lifetime, descriptor.ServiceType, descriptor.ImplementationType, callSiteChain); } else { throw new InvalidOperationException(SR.InvalidServiceDescriptor); } return(_callSiteCache[callSiteKey] = callSite); } return(null); }
private ServiceCallSite TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot, bool throwOnConstraintViolation) { if (serviceType.IsConstructedGenericType && serviceType.GetGenericTypeDefinition() == descriptor.ServiceType) { Debug.Assert(descriptor.ImplementationType != null, "descriptor.ImplementationType != null"); var lifetime = new ResultCache(descriptor.Lifetime, serviceType, slot); Type closedType; try { closedType = descriptor.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments); } catch (ArgumentException ex) { if (throwOnConstraintViolation) { throw new InvalidOperationException(SR.Format(SR.GenericConstraintViolation, serviceType, descriptor.ImplementationType), ex); } return(null); } return(CreateConstructorCallSite(lifetime, serviceType, closedType, callSiteChain)); } return(null); }
private ServiceCallSite TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot, bool throwOnConstraintViolation) { if (serviceType.IsConstructedGenericType && serviceType.GetGenericTypeDefinition() == descriptor.ServiceType) { ServiceCacheKey callSiteKey = new ServiceCacheKey(serviceType, slot); if (_callSiteCache.TryGetValue(callSiteKey, out ServiceCallSite serviceCallSite)) { return(serviceCallSite); } Debug.Assert(descriptor.ImplementationType != null, "descriptor.ImplementationType != null"); var lifetime = new ResultCache(descriptor.Lifetime, serviceType, slot); Type closedType; try { closedType = descriptor.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments); } catch (ArgumentException) { if (throwOnConstraintViolation) { throw; } return(null); } return(_callSiteCache[callSiteKey] = CreateConstructorCallSite(lifetime, serviceType, closedType, callSiteChain)); } return(null); }
private ServiceCallSite TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot) { if (serviceType == descriptor.ServiceType) { ServiceCallSite callSite; var lifetime = new ResultCache(descriptor.Lifetime, serviceType, slot); if (descriptor.ImplementationInstance != null) { callSite = new ConstantCallSite(descriptor.ServiceType, descriptor.ImplementationInstance); } else if (descriptor.ImplementationFactory != null) { callSite = new FactoryCallSite(lifetime, descriptor.ServiceType, descriptor.ImplementationFactory); } else if (descriptor.ImplementationType != null) { callSite = CreateConstructorCallSite(lifetime, descriptor.ServiceType, descriptor.ImplementationType, callSiteChain); } else { throw new InvalidOperationException("Invalid service descriptor"); } return(callSite); } return(null); }
public ConstructorCallSite(ResultCache cache, Type serviceType, ConstructorInfo constructorInfo, ServiceCallSite[] parameterCallSites) : base(cache) { if (!serviceType.IsAssignableFrom(constructorInfo.DeclaringType)) { throw new ArgumentException(SR.Format(SR.ImplementationTypeCantBeConvertedToServiceType, constructorInfo.DeclaringType, serviceType)); } ServiceType = serviceType; ConstructorInfo = constructorInfo; ParameterCallSites = parameterCallSites; }
private ServiceCallSite TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot) { if (serviceType.IsConstructedGenericType && serviceType.GetGenericTypeDefinition() == descriptor.ServiceType) { Debug.Assert(descriptor.ImplementationType != null, "descriptor.ImplementationType != null"); var lifetime = new ResultCache(descriptor.Lifetime, serviceType, slot); Type closedType = descriptor.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments); return(CreateConstructorCallSite(lifetime, serviceType, closedType, callSiteChain)); } return(null); }
/// <summary> /// 根据注册服务类型的泛型参数制造一个实现类型参数,然后调用CreateConstructorCallSite()进行实例化ServiceCallSite,所以泛型只能以构造器实例方式 /// </summary> /// <param name="descriptor"></param> /// <param name="serviceType"></param> /// <param name="callSiteChain"></param> /// <param name="slot"></param> /// <returns></returns> private ServiceCallSite TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot) { // 如果当前泛型类型为封闭并且当前注册的基类类型为当前泛型的开放类型,则实例化,否则返回null if (serviceType.IsConstructedGenericType && serviceType.GetGenericTypeDefinition() == descriptor.ServiceType) { Debug.Assert(descriptor.ImplementationType != null, "descriptor.ImplementationType != null"); var lifetime = new ResultCache(descriptor.Lifetime, serviceType, slot); //利用当前注册服务的声明和生命周期类型实例化一个结果缓存配置 var closedType = descriptor.ImplementationType.MakeGenericType(serviceType .GenericTypeArguments); //利用注册类型泛型参数创造派生类封闭泛型类型 return(CreateConstructorCallSite(lifetime, serviceType, closedType, callSiteChain)); } return(null); }
/// <summary> /// 根据注册服务的方式进行实例化 /// </summary> /// <param name="descriptor"></param> /// <param name="serviceType"></param> /// <param name="callSiteChain"></param> /// <param name="slot"></param> /// <returns></returns> /// <exception cref="InvalidOperationException"></exception> private ServiceCallSite TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot) { //判断基类类型是否与ServiceDescriptor所持有的基类类型是否一致,如果不一致直接返回false if (serviceType == descriptor.ServiceType) { //根据当前注册的生命周期,基类类型和slot实例化一个ResultCache,ResultCache类型具有一个最后结果缓存的位置(相当于跟生命周期一致)和一个缓存Key ServiceCallSite callSite; var lifetime = new ResultCache(descriptor.Lifetime, serviceType, slot); //根据注册时所使用的方式来创建不同的ServiceCallSite,共具有三种ServiceCallSite子类 if (descriptor.ImplementationInstance != null) { //注册时直接根据对象进行实例化具体对象(Singleton生命周期独有) callSite = new ConstantCallSite(descriptor.ServiceType, descriptor.ImplementationInstance); } else if (descriptor.ImplementationFactory != null) { //FactoryCallSite 注册时根据一个工厂实例化对象 callSite = new FactoryCallSite(lifetime, descriptor.ServiceType, descriptor.ImplementationFactory); } else if (descriptor.ImplementationType != null) { //ConstructorCallSite 注册时根据具体实例类型进行实例化对象,如果注册类型是使用的派生类类型方式,则调用CreateConstructorCallSite来实例化一个ConstructorCallSite callSite = CreateConstructorCallSite(lifetime, descriptor.ServiceType, descriptor.ImplementationType, callSiteChain); } else { throw new InvalidOperationException("Invalid service descriptor"); } return(callSite); } return(null); }
private ServiceCallSite CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain) { try { callSiteChain.Add(serviceType, implementationType); ConstructorInfo[] constructors = implementationType.GetTypeInfo() .DeclaredConstructors .Where(constructor => constructor.IsPublic) .ToArray(); ServiceCallSite[] parameterCallSites = null; if (constructors.Length == 0) { throw new InvalidOperationException(SR.Format(SR.NoConstructorMatch, implementationType)); } else if (constructors.Length == 1) { ConstructorInfo constructor = constructors[0]; ParameterInfo[] parameters = constructor.GetParameters(); if (parameters.Length == 0) { return(new ConstructorCallSite(lifetime, serviceType, constructor)); } parameterCallSites = CreateArgumentCallSites( serviceType, implementationType, callSiteChain, parameters, throwIfCallSiteNotFound: true); return(new ConstructorCallSite(lifetime, serviceType, constructor, parameterCallSites)); } Array.Sort(constructors, (a, b) => b.GetParameters().Length.CompareTo(a.GetParameters().Length)); ConstructorInfo bestConstructor = null; HashSet <Type> bestConstructorParameterTypes = null; for (int i = 0; i < constructors.Length; i++) { ParameterInfo[] parameters = constructors[i].GetParameters(); ServiceCallSite[] currentParameterCallSites = CreateArgumentCallSites( serviceType, implementationType, callSiteChain, parameters, throwIfCallSiteNotFound: false); if (currentParameterCallSites != null) { if (bestConstructor == null) { bestConstructor = constructors[i]; parameterCallSites = currentParameterCallSites; } else { // Since we're visiting constructors in decreasing order of number of parameters, // we'll only see ambiguities or supersets once we've seen a 'bestConstructor'. if (bestConstructorParameterTypes == null) { bestConstructorParameterTypes = new HashSet <Type>( bestConstructor.GetParameters().Select(p => p.ParameterType)); } if (!bestConstructorParameterTypes.IsSupersetOf(parameters.Select(p => p.ParameterType))) { // Ambiguous match exception string message = string.Join( Environment.NewLine, SR.Format(SR.AmbiguousConstructorException, implementationType), bestConstructor, constructors[i]); throw new InvalidOperationException(message); } } } } if (bestConstructor == null) { throw new InvalidOperationException( SR.Format(SR.UnableToActivateTypeException, implementationType)); } else { Debug.Assert(parameterCallSites != null); return(new ConstructorCallSite(lifetime, serviceType, bestConstructor, parameterCallSites)); } } finally { callSiteChain.Remove(serviceType); } }
public ConstructorCallSite(ResultCache cache, Type serviceType, ConstructorInfo constructorInfo) : this(cache, serviceType, constructorInfo, Array.Empty <ServiceCallSite>()) { }
public ConstructorCallSite(ResultCache cache, Type serviceType, ConstructorInfo constructorInfo) : this(cache, serviceType, constructorInfo, new ServiceCallSite[0]) { }
private ServiceCallSite CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain) { callSiteChain.Add(serviceType, implementationType); var constructors = implementationType .GetConstructors() .Where(constructor => constructor.IsPublic) .ToArray(); ServiceCallSite[] parameterCallSites = null; if (constructors.Length == 0) { throw new InvalidOperationException(string.Format("A suitable constructor for type '{0}' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.", implementationType)); } else if (constructors.Length == 1) { var constructor = constructors[0]; var parameters = constructor.GetParameters(); if (parameters.Length == 0) { return(new ConstructorCallSite(lifetime, serviceType, constructor)); } parameterCallSites = CreateArgumentCallSites( serviceType, implementationType, callSiteChain, parameters, throwIfCallSiteNotFound: true); return(new ConstructorCallSite(lifetime, serviceType, constructor, parameterCallSites)); } Array.Sort(constructors, (a, b) => b.GetParameters().Length.CompareTo(a.GetParameters().Length)); ConstructorInfo bestConstructor = null; HashSet <Type> bestConstructorParameterTypes = null; for (var i = 0; i < constructors.Length; i++) { var parameters = constructors[i].GetParameters(); var currentParameterCallSites = CreateArgumentCallSites( serviceType, implementationType, callSiteChain, parameters, throwIfCallSiteNotFound: false); if (currentParameterCallSites != null) { if (bestConstructor == null) { bestConstructor = constructors[i]; parameterCallSites = currentParameterCallSites; } else { // Since we're visiting constructors in decreasing order of number of parameters, // we'll only see ambiguities or supersets once we've seen a 'bestConstructor'. if (bestConstructorParameterTypes == null) { bestConstructorParameterTypes = new HashSet <Type>( bestConstructor.GetParameters().Select(p => p.ParameterType)); } if (!bestConstructorParameterTypes.IsSupersetOf(parameters.Select(p => p.ParameterType))) { // Ambiguous match exception var message = string.Join( Environment.NewLine, string.Format("Unable to activate type '{0}'. The following constructors are ambiguous:", implementationType), bestConstructor, constructors[i]); throw new InvalidOperationException(message); } } } } if (bestConstructor == null) { throw new InvalidOperationException( string.Format("No constructor for type '{0}' can be instantiated using services from the service container and default values.", implementationType)); } else { Debug.Assert(parameterCallSites != null); return(new ConstructorCallSite(lifetime, serviceType, bestConstructor, parameterCallSites)); } }
private ServiceCallSite TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain) { try { callSiteChain.Add(serviceType); if (serviceType.IsConstructedGenericType && serviceType.GetGenericTypeDefinition() == typeof(IEnumerable <>)) { Type itemType = serviceType.GenericTypeArguments[0]; CallSiteResultCacheLocation cacheLocation = CallSiteResultCacheLocation.Root; var callSites = new List <ServiceCallSite>(); // If item type is not generic we can safely use descriptor cache if (!itemType.IsConstructedGenericType && _descriptorLookup.TryGetValue(itemType, out ServiceDescriptorCacheItem descriptors)) { for (int i = 0; i < descriptors.Count; i++) { ServiceDescriptor descriptor = descriptors[i]; // Last service should get slot 0 int slot = descriptors.Count - i - 1; // There may not be any open generics here ServiceCallSite callSite = TryCreateExact(descriptor, itemType, callSiteChain, slot); Debug.Assert(callSite != null); cacheLocation = GetCommonCacheLocation(cacheLocation, callSite.Cache.Location); callSites.Add(callSite); } } else { int slot = 0; // We are going in reverse so the last service in descriptor list gets slot 0 for (int i = _descriptors.Count - 1; i >= 0; i--) { ServiceDescriptor descriptor = _descriptors[i]; ServiceCallSite callSite = TryCreateExact(descriptor, itemType, callSiteChain, slot) ?? TryCreateOpenGeneric(descriptor, itemType, callSiteChain, slot); if (callSite != null) { slot++; cacheLocation = GetCommonCacheLocation(cacheLocation, callSite.Cache.Location); callSites.Add(callSite); } } callSites.Reverse(); } ResultCache resultCache = ResultCache.None; if (cacheLocation == CallSiteResultCacheLocation.Scope || cacheLocation == CallSiteResultCacheLocation.Root) { resultCache = new ResultCache(cacheLocation, new ServiceCacheKey(serviceType, DefaultSlot)); } return(new IEnumerableCallSite(resultCache, itemType, callSites.ToArray())); } return(null); } finally { callSiteChain.Remove(serviceType); } }
public ConstructorCallSite(ResultCache cache, Type serviceType, ConstructorInfo constructorInfo, ServiceCallSite[] parameterCallSites) : base(cache) { ServiceType = serviceType; ConstructorInfo = constructorInfo; ParameterCallSites = parameterCallSites; }
public FactoryCallSite(ResultCache cache, Type serviceType, Func <IServiceProvider, object> factory) : base(cache) { Factory = factory; ServiceType = serviceType; }
public IEnumerableCallSite(ResultCache cache, Type itemType, ServiceCallSite[] serviceCallSites) : base(cache) { ItemType = itemType; ServiceCallSites = serviceCallSites; }
protected ServiceCallSite(ResultCache cache) { Cache = cache; }
/// <summary> /// 选择最优构造器并实例化ConstructorCallSite对象, /// </summary> /// <param name="lifetime"></param> /// <param name="serviceType"></param> /// <param name="implementationType"></param> /// <param name="callSiteChain"></param> /// <returns></returns> /// <exception cref="InvalidOperationException"></exception> private ServiceCallSite CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain) { //将此服务类型和实例类型存入callSiteChain callSiteChain.Add(serviceType, implementationType); //获取实例类型的所有公共构造器,然后选择其最优的构造器并创建ConstructorCallSite var constructors = implementationType.GetTypeInfo() .DeclaredConstructors .Where(constructor => constructor.IsPublic) .ToArray(); ServiceCallSite[] parameterCallSites = null; if (constructors.Length == 0) { //首先获取实例类型的所有公共构造器,如果不存在就抛出异常 throw new InvalidOperationException(Resources.FormatNoConstructorMatch(implementationType)); } else if (constructors.Length == 1) { //如果此类型只有一个构造器,那么就使用此构造器当做最优构造器进行实例化 var constructor = constructors[0]; var parameters = constructor.GetParameters(); if (parameters.Length == 0) { return(new ConstructorCallSite(lifetime, serviceType, constructor)); } //如果此类型具有多个构造器,那么就选出最优构造器 parameterCallSites = CreateArgumentCallSites( serviceType, implementationType, callSiteChain, parameters, throwIfCallSiteNotFound: true); return(new ConstructorCallSite(lifetime, serviceType, constructor, parameterCallSites)); } // 如果没有找到最优构造器,就抛出异常,存在最优构造器就以此构造器实例化ConstructorCallSite Array.Sort(constructors, (a, b) => b.GetParameters().Length.CompareTo(a.GetParameters().Length)); ConstructorInfo bestConstructor = null; HashSet <Type> bestConstructorParameterTypes = null; for (var i = 0; i < constructors.Length; i++) { var parameters = constructors[i].GetParameters(); var currentParameterCallSites = CreateArgumentCallSites( serviceType, implementationType, callSiteChain, parameters, throwIfCallSiteNotFound: false); if (currentParameterCallSites != null) { if (bestConstructor == null) { bestConstructor = constructors[i]; parameterCallSites = currentParameterCallSites; } else { // Since we're visiting constructors in decreasing order of number of parameters, // we'll only see ambiguities or supersets once we've seen a 'bestConstructor'. if (bestConstructorParameterTypes == null) { bestConstructorParameterTypes = new HashSet <Type>( bestConstructor.GetParameters().Select(p => p.ParameterType)); } if (!bestConstructorParameterTypes.IsSupersetOf(parameters.Select(p => p.ParameterType))) { // Ambiguous match exception var message = string.Join( Environment.NewLine, Resources.FormatAmbiguousConstructorException(implementationType), bestConstructor, constructors[i]); throw new InvalidOperationException(message); } } } } if (bestConstructor == null) { throw new InvalidOperationException( Resources.FormatUnableToActivateTypeException(implementationType)); } else { Debug.Assert(parameterCallSites != null); return(new ConstructorCallSite(lifetime, serviceType, bestConstructor, parameterCallSites)); } }
// 在这个方法中会选择服务实例类型中的最优构造器,并实例化一个ConstructorCallSite对象。 private ServiceCallSite CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain) { callSiteChain.Add(serviceType, implementationType); // 获取实例类型的所有公共构造器 // 然后选择其最优的构造器并创建 ConstructorCallSite var constructors = implementationType.GetTypeInfo() .DeclaredConstructors .Where(constructor => constructor.IsPublic) .ToArray(); ServiceCallSite[] parameterCallSites = null; if (constructors.Length == 0) { // 没有公共构造器,直接抛出异常。 throw new InvalidOperationException(Resources.FormatNoConstructorMatch(implementationType)); } else if (constructors.Length == 1) { // 如果当前构造器为1个,则判断构造器是否存在参数并将所有参数进行实例化(创建指定的 ServiceCallSite) var constructor = constructors[0]; // 获取当前构造器的所有参数,并对参数一一进行创建 ServiceCallSite 递归调用 var parameters = constructor.GetParameters(); if (parameters.Length == 0) { // 如果构造器参数为0个,则直接为该服务实例类型创建 ConstructorCallSite return(new ConstructorCallSite(lifetime, serviceType, constructor)); } // 创建当前构造器的所有参数的 CallSite // 如果有未知的参数(_descriptorLookup 未记录的参数), 则直接抛出异常 parameterCallSites = CreateArgumentCallSites( serviceType, implementationType, callSiteChain, parameters, throwIfCallSiteNotFound: true); return(new ConstructorCallSite(lifetime, serviceType, constructor, parameterCallSites)); } // 根据构造器参数的长度进行排序,下面会判断所有构造器中是否具有未知参数 Array.Sort(constructors, (a, b) => b.GetParameters().Length.CompareTo(a.GetParameters().Length)); // 最优构造器 ConstructorInfo bestConstructor = null; // 最优参数类型集合 HashSet <Type> bestConstructorParameterTypes = null; for (var i = 0; i < constructors.Length; i++) { var parameters = constructors[i].GetParameters(); // 创建当前构造器的所有参数的 CallSite // 如果具有未知的参数,则不抛出异常 var currentParameterCallSites = CreateArgumentCallSites( serviceType, implementationType, callSiteChain, parameters, throwIfCallSiteNotFound: false); if (currentParameterCallSites != null) { // 如果所有参数的 CallSite 构造成功,并且最优构造函数对象为空,则将当前构造器设置为最优构造器。 if (bestConstructor == null) { bestConstructor = constructors[i]; parameterCallSites = currentParameterCallSites; } else { if (bestConstructorParameterTypes == null) { // 如果最优参数类型集合为空,则将最优构造器的参数赋给集合。 bestConstructorParameterTypes = new HashSet <Type>( bestConstructor.GetParameters().Select(p => p.ParameterType)); } if (!bestConstructorParameterTypes.IsSupersetOf(parameters.Select(p => p.ParameterType))) { // 如果最优参数类型集合不为当前构造函数的参数集合的自己,则抛出异常 var message = string.Join( Environment.NewLine, Resources.FormatAmbiguousConstructorException(implementationType), bestConstructor, constructors[i]); throw new InvalidOperationException(message); } } } } if (bestConstructor == null) { // 如果为找到最优构造函数,则抛出异常 throw new InvalidOperationException( Resources.FormatUnableToActivateTypeException(implementationType)); } else { // 实例化一个 ConstructorCallSite 对象并返回。 Debug.Assert(parameterCallSites != null); return(new ConstructorCallSite(lifetime, serviceType, bestConstructor, parameterCallSites)); } }