protected override Type VisitIEnumerable(IEnumerableCallSite enumerableCallSite, CallSiteValidatorState state) { Type result = null; foreach (var serviceCallSite in enumerableCallSite.ServiceCallSites) { var scoped = VisitCallSite(serviceCallSite, state); if (result == null) { result = scoped; } } return(result); }
protected override Expression VisitIEnumerable(IEnumerableCallSite callSite, object context) { if (callSite.ServiceCallSites.Length == 0) { return(Expression.Constant( ServiceLookupHelpers.GetArrayEmptyMethodInfo(callSite.ItemType) .Invoke(obj: null, parameters: Array.Empty <object>()))); } return(Expression.NewArrayInit( callSite.ItemType, callSite.ServiceCallSites.Select(cs => Convert( VisitCallSite(cs, context), callSite.ItemType)))); }
protected override Expression VisitIEnumerable(IEnumerableCallSite callSite, CallSiteExpressionBuilderContext context) { if (callSite.ServiceCallSites.Length == 0) { return(Expression.Constant(ArrayEmptyMethodInfo .MakeGenericMethod(callSite.ItemType) .Invoke(obj: null, parameters: new object[0]))); } return(Expression.NewArrayInit( callSite.ItemType, callSite.ServiceCallSites.Select(cs => Convert( VisitCallSite(cs, context), callSite.ItemType)))); }
protected abstract TResult VisitIEnumerable(IEnumerableCallSite enumerableCallSite, TArgument argument);
private ServiceCallSite TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain) { ServiceCacheKey callSiteKey = new ServiceCacheKey(serviceType, DefaultSlot); if (_callSiteCache.TryGetValue(callSiteKey, out ServiceCallSite serviceCallSite)) { return(serviceCallSite); } 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.Length - 1; i >= 0; i--) { ServiceDescriptor descriptor = _descriptors[i]; ServiceCallSite callSite = TryCreateExact(descriptor, itemType, callSiteChain, slot) ?? TryCreateOpenGeneric(descriptor, itemType, callSiteChain, slot, false); 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, callSiteKey); } return(_callSiteCache[callSiteKey] = new IEnumerableCallSite(resultCache, itemType, callSites.ToArray())); } return(null); } finally { callSiteChain.Remove(serviceType); } }