public CastedExpressionBindingProperty ConvertExpressionToType(ParsedExpressionBindingProperty exprP, ExpectedTypeBindingProperty expectedTypeP = null) { var expr = exprP.Expression; var expectedType = expectedTypeP?.Type ?? typeof(object); if (expectedType == typeof(object)) { expectedType = typeof(Command); } if (!typeof(Delegate).IsAssignableFrom(expectedType)) { throw new Exception($"Command bindings must be assigned to properties of Delegate type, not { expectedType }"); } var normalConvert = TypeConversion.ImplicitConversion(expr, expectedType); if (normalConvert != null && expr.Type != typeof(object)) { return(new CastedExpressionBindingProperty(normalConvert)); } // wrap expression into a lambda if (typeof(Delegate).IsAssignableFrom(expectedType) && !typeof(Delegate).IsAssignableFrom(expr.Type)) { var invokeMethod = expectedType.GetMethod("Invoke"); expr = TaskConversion(expr, invokeMethod.ReturnType); return(new CastedExpressionBindingProperty(Expression.Lambda( expectedType, expr, invokeMethod.GetParameters().Select(p => Expression.Parameter(p.ParameterType, p.Name)) ))); } // TODO: convert delegates to another delegates throw new Exception($"Can not convert expression '{ expr }' to '{expectedType}'."); }
protected override Expression ConvertExpressionToType(Expression expr, Type expectedType) { if (expectedType == typeof(object)) { expectedType = typeof(Command); } if (!typeof(Delegate).IsAssignableFrom(expectedType)) { throw new Exception($"Command bindings must be assigned to properties with Delegate type, not { expectedType }"); } var normalConvert = TypeConversion.ImplicitConversion(expr, expectedType); if (normalConvert != null && expr.Type != typeof(object)) { return(normalConvert); } if (typeof(Delegate).IsAssignableFrom(expectedType) && !typeof(Delegate).IsAssignableFrom(expr.Type)) { var invokeMethod = expectedType.GetMethod("Invoke"); expr = TaskConversion(expr, invokeMethod.ReturnType); return(Expression.Lambda( expectedType, base.ConvertExpressionToType(expr, invokeMethod.ReturnType), invokeMethod.GetParameters().Select(p => Expression.Parameter(p.ParameterType, p.Name)) )); } // TODO: convert delegates to another delegates throw new Exception($"Can not convert expression '{ expr }' to '{expectedType}'."); }
protected string EmitCreateControl(Type type, object[] arguments) { // if matching ctor exists, invoke it directly if (type.GetTypeInfo().GetCustomAttribute(typeof(DependencyInjection.RequireDependencyInjectionAttribute)) is DependencyInjection.RequireDependencyInjectionAttribute requireDiAttr) { return(emitter.EmitCustomInjectionFactoryInvocation(requireDiAttr.FactoryType, type)); } else if (type.GetConstructors().Any(ctor => ctor.GetParameters().Length == (arguments?.Length ?? 0) && ctor.GetParameters().Zip(arguments ?? Enumerable.Empty <object>(), (p, a) => TypeConversion.ImplicitConversion(Expression.Constant(a), p.ParameterType)) .All(a => a != null))) { return(emitter.EmitCreateObject(type, arguments)); } // othervise invoke DI factory else { return(emitter.EmitInjectionFactoryInvocation( type, (arguments ?? Enumerable.Empty <object>()).Select(a => (a.GetType(), emitter.EmitValue(a))).ToArray(), emitter.InvokeDefaultInjectionFactory )); } }
/// <summary> /// Creates the binding by calling .ctor(BindingCompilationService service, object[] properties), does not wrap exceptions to TargetInvocationException. /// </summary> public static IBinding CreateBinding(this BindingCompilationService service, Type binding, object[] properties) { if (binding.GetTypeInfo().ContainsGenericParameters) { var nonGenericBase = binding.GetTypeInfo().BaseType; Debug.Assert(!nonGenericBase.GetTypeInfo().ContainsGenericParameters&& nonGenericBase.Name + "`1" == binding.Name); var tmpBinding = CreateBinding(service, nonGenericBase, properties); var type = tmpBinding.GetProperty <ExpectedTypeBindingProperty>(ErrorHandlingMode.ReturnNull)?.Type ?? tmpBinding.GetProperty <ResultTypeBindingProperty>(ErrorHandlingMode.ThrowException).Type; binding = binding.MakeGenericType(new [] { type }); properties = tmpBinding is ICloneableBinding cloneable?cloneable.GetAllComputedProperties().ToArray() : properties; } return(bindingCtorCache.GetOrAdd(binding, type => { var ctor = type.GetConstructor(new[] { typeof(BindingCompilationService), typeof(object[]) }) ?? type.GetConstructor(new[] { typeof(BindingCompilationService), typeof(IEnumerable <object>) }); if (ctor == null) { throw new NotSupportedException($"Could not find .ctor(BindingCompilationService service, object[] properties) on binding '{binding.FullName}'."); } var bindingServiceParam = Expression.Parameter(typeof(BindingCompilationService)); var propertiesParam = Expression.Parameter(typeof(object[])); var expression = Expression.New(ctor, bindingServiceParam, TypeConversion.ImplicitConversion(propertiesParam, ctor.GetParameters()[1].ParameterType)); return Expression.Lambda <Func <BindingCompilationService, object[], IBinding> >(expression, bindingServiceParam, propertiesParam).Compile(); })(service, properties)); }
public void Conversion_ValidToString() { TypeConversion.ImplicitConversion(Expression.Parameter(typeof(DateTime)), typeof(string), throwException: true, allowToString: true); TypeConversion.ImplicitConversion(Expression.Parameter(typeof(int)), typeof(string), throwException: true, allowToString: true); TypeConversion.ImplicitConversion(Expression.Parameter(typeof(string)), typeof(string), throwException: true, allowToString: true); TypeConversion.ImplicitConversion(Expression.Parameter(typeof(double)), typeof(string), throwException: true, allowToString: true); TypeConversion.ImplicitConversion(Expression.Parameter(typeof(TimeSpan)), typeof(string), throwException: true, allowToString: true); TypeConversion.ImplicitConversion(Expression.Parameter(typeof(Tuple <int, int>)), typeof(string), throwException: true, allowToString: true); }
/// <summary> /// Creates the binding by calling .ctor(BindingCompilationService service, object[] properties), does not wrap exceptions to TargetInvocationException. /// </summary> public static IBinding CreateBinding(this BindingCompilationService service, Type binding, object[] properties) => bindingCtorCache.GetOrAdd(binding, type => { var ctor = type.GetConstructor(new[] { typeof(BindingCompilationService), typeof(object[]) }) ?? type.GetConstructor(new[] { typeof(BindingCompilationService), typeof(IEnumerable <object>) }); if (ctor == null) { throw new NotSupportedException($"Could not find .ctor(BindingCompilationService service, object[] properties) on binding '{binding.FullName}'."); } var bindingServiceParam = Expression.Parameter(typeof(BindingCompilationService)); var propertiesParam = Expression.Parameter(typeof(object[])); var expression = Expression.New(ctor, bindingServiceParam, TypeConversion.ImplicitConversion(propertiesParam, ctor.GetParameters()[1].ParameterType)); return(Expression.Lambda <Func <BindingCompilationService, object[], IBinding> >(expression, bindingServiceParam, propertiesParam).Compile()); })(service, properties);
public string CompileBinding(string expression, Type[] contexts, Type expectedType) { var context = new DataContextStack(contexts.FirstOrDefault() ?? typeof(object), rootControlType: typeof(DotvvmControl)); for (int i = 1; i < contexts.Length; i++) { context = new DataContextStack(contexts[i], context); } var parser = new BindingExpressionBuilder(); var expressionTree = TypeConversion.ImplicitConversion(parser.Parse(expression, context, BindingParserOptions.Create <ValueBindingExpression>()), expectedType, true, true); return(JavascriptTranslator.CompileToJavascript(expressionTree, context)); }
public string CompileBinding(string expression, Type[] contexts, Type expectedType) { var context = DataContextStack.Create(contexts.FirstOrDefault() ?? typeof(object), extensionParameters: new BindingExtensionParameter[] { new BindingPageInfoExtensionParameter(), }.Concat(configuration.Markup.DefaultExtensionParameters).ToArray()); for (int i = 1; i < contexts.Length; i++) { context = DataContextStack.Create(contexts[i], context); } var parser = new BindingExpressionBuilder(); var expressionTree = TypeConversion.ImplicitConversion(parser.Parse(expression, context, BindingParserOptions.Create <ValueBindingExpression>()), expectedType, true, true); var jsExpression = new JsParenthesizedExpression(configuration.ServiceProvider.GetRequiredService <JavascriptTranslator>().CompileToJavascript(expressionTree, context)); jsExpression.AcceptVisitor(new KnockoutObservableHandlingVisitor(true)); JsTemporaryVariableResolver.ResolveVariables(jsExpression); return(JavascriptTranslator.FormatKnockoutScript(jsExpression.Expression)); }
protected string EmitCreateControl(Type type, object[] arguments) { // if marked with [RequireDependencyInjection] attribute, invoke injected factory if (type.GetTypeInfo().GetCustomAttribute(typeof(DependencyInjection.RequireDependencyInjectionAttribute)) is DependencyInjection.RequireDependencyInjectionAttribute requireDiAttr) { return(emitter.EmitCustomInjectionFactoryInvocation(requireDiAttr.FactoryType, type)); } // if matching ctor exists, invoke it directly else if (type.GetConstructors().FirstOrDefault(ctor => ctor.GetParameters().Count(p => !p.HasDefaultValue) <= (arguments?.Length ?? 0) && ctor.GetParameters().Length >= (arguments?.Length ?? 0) && ctor.GetParameters().Zip(arguments ?? Enumerable.Empty <object>(), (p, a) => TypeConversion.ImplicitConversion(Expression.Constant(a), p.ParameterType)) .All(a => a != null)) is ConstructorInfo constructor) { var optionalArguments = constructor.GetParameters().Skip(arguments?.Length ?? 0) .Select(a => a.ParameterType == typeof(bool) && a.Name == "allowImplicitLifecycleRequirements" ? false : a.DefaultValue ); return(emitter.EmitCreateObject(type, arguments == null ? optionalArguments.ToArray() : arguments.Concat(optionalArguments).ToArray())); } // otherwise invoke DI factory else { return(emitter.EmitInjectionFactoryInvocation( type, (arguments ?? Enumerable.Empty <object>()).Select(a => (a.GetType(), emitter.EmitValue(a))).ToArray(), emitter.InvokeDefaultInjectionFactory )); } }
protected virtual Expression ConvertExpressionToType(Expression expr, Type expectedType) => TypeConversion.ImplicitConversion(expr, expectedType, throwException: true, allowToString: true);
public void Conversion_InvalidToString() { // System.Linq.Expression does not override ToString, so the conversion is invalid Assert.IsNull(TypeConversion.ImplicitConversion(Expression.Parameter(typeof(Expression)), typeof(string))); Assert.IsNull(TypeConversion.ImplicitConversion(Expression.Parameter(typeof(object)), typeof(string))); }
public void Conversion_IntToDouble() { TypeConversion.ImplicitConversion(Expression.Parameter(typeof(int)), typeof(double), throwException: true); }
public void Conversion_DoubleNullable() { TypeConversion.ImplicitConversion(Expression.Parameter(typeof(double)), typeof(double?), throwException: true); }