private object GetTag([NotNull] Expression tagExpression) { if (tagExpression == null) { throw new ArgumentNullException(nameof(tagExpression)); } switch (tagExpression) { case ConstantExpression constant: return(constant.Value); case UnaryExpression unary: if (unary.NodeType == ExpressionType.Convert) { return(GetTag(unary.Operand)); } break; } // ReSharper disable once ConstantNullCoalescingCondition var expression = Visit(tagExpression) ?? throw new BuildExpressionException($"Invalid tag expression {tagExpression}.", new InvalidOperationException()); if (_buildContext.TryCompile(Expression.Lambda(expression.Convert(typeof(object)), true), out var tagFunc, out var error)) { return(((Func <object>)tagFunc)()); } throw error; }
private object GetTag([NotNull] Expression tagExpression) { if (tagExpression == null) { throw new ArgumentNullException(nameof(tagExpression)); } object tag; switch (tagExpression) { case ConstantExpression constant: tag = constant.Value; break; default: // ReSharper disable once ConstantNullCoalescingCondition var expression = Visit(tagExpression) ?? throw new BuildExpressionException($"Invalid tag expression {tagExpression}.", new InvalidOperationException()); if (_buildContext.TryCompile(Expression.Lambda(expression, true), out var tagFunc, out var error)) { tag = ((Func <object>)tagFunc)(); } else { throw error; } break; }
public bool TryBuildExpression(IBuildContext buildContext, ILifetime lifetime, out Expression expression, out Exception error) { var type = buildContext.Key.Type.Descriptor(); var keyComparer = buildContext.Key.Tag as IComparer <Key>; if (!type.IsConstructedGenericType()) { throw new BuildExpressionException($"Unsupported enumerable type {type}.", null); } var genericTypeArguments = type.GetGenericTypeArguments(); if (genericTypeArguments.Length != 1) { throw new BuildExpressionException($"Unsupported enumerable type {type}.", null); } var elementType = genericTypeArguments[0]; var allKeys = GetKeys(buildContext.Container, elementType); if (keyComparer != null) { allKeys = allKeys.OrderBy(i => i, keyComparer); } var keys = allKeys.ToArray(); var positionVar = Expression.Variable(typeof(int)); var conditionExpression = keys.Length < 5 ? CreateConditions(buildContext, keys, elementType, positionVar) : CreateSwitchCases(buildContext, keys, elementType, positionVar); if (buildContext.TryCompile(Expression.Lambda(conditionExpression, positionVar, buildContext.ContainerParameter, buildContext.ArgsParameter), out var factory, out error)) { var ctor = EnumerableTypeDescriptor.MakeGenericType(elementType).Descriptor().GetDeclaredConstructors().Single(); var enumerableExpression = Expression.New(ctor, Expression.Constant(factory), Expression.Constant(keys.Length), buildContext.ContainerParameter, buildContext.ArgsParameter); expression = enumerableExpression; return(true); } expression = default(Expression); return(false); }