public void Should_not_allow_implicit_boxing_for_instance_expression() { MethodInfo objToStringInfo = typeof(object).GetMethod("ToString"); var ex = Assert.Throws <ArgumentException>(() => Expr.Call(Expr.Constant(22), objToStringInfo)); Assert.That(ex.Message, Is.StringContaining("Instance expression of type System.Int32 does not match to type: System.Object")); }
/// <summary> /// Converts a value from one type to another /// </summary> /// <param name="value">The value to convert</param> /// <param name="type">The type to convert the value to</param> /// <returns>The value converted to the requested type</returns> public static object ChangeType(object value, Type type) { if (value != null && value.GetType() == type) { return(value); } var expression = (Expression)Expression.Constant(value); // Special case for converting from string to enum for metadata filters if (expression.Type == typeof(SqlString) && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>) && type.GetGenericArguments()[0].IsEnum) { var nullCheck = NullCheck(expression); var nullValue = (Expression)Expression.Constant(null); nullValue = Expression.Convert(nullValue, type); var parsedValue = (Expression)Expression.Convert(expression, typeof(string)); parsedValue = Expr.Call(() => Enum.Parse(Expr.Arg <Type>(), Expr.Arg <string>(), Expr.Arg <bool>()), Expression.Constant(type.GetGenericArguments()[0]), parsedValue, Expression.Constant(true)); parsedValue = Expression.Convert(parsedValue, type); expression = Expression.Condition(nullCheck, nullValue, parsedValue); } else if (expression.Type == typeof(SqlString) && type.IsEnum) { expression = (Expression)Expression.Convert(expression, typeof(string)); expression = Expr.Call(() => Enum.Parse(Expr.Arg <Type>(), Expr.Arg <string>(), Expr.Arg <bool>()), Expression.Constant(type), expression, Expression.Constant(true)); expression = Expression.Convert(expression, type); } else { expression = Expression.Convert(expression, type); } expression = Expression.Convert(expression, typeof(object)); return(Expression.Lambda <Func <object> >(expression).Compile()()); }
public void Should_properly_map_parameters_with_this() { MethodInfo mi = typeof(DerivedType).GetMethod("Call"); var func = CreateFunc <DerivedType, int, DerivedType>(Expr.Return(Expr.Call(Expr.Parameter(0, typeof(DerivedType)), mi, Expr.Parameter(1, typeof(int))))); var obj = func(new DerivedType(), 32); Assert.That(obj.X, Is.EqualTo(32)); }
public void Should_call_virtual_method() { var virtualMethodInfo = typeof(BaseClass).GetMethod("Virt"); var func = CreateFunc <BaseClass, string>(Expr.Return(Expr.Call(Expr.Parameter(0, typeof(BaseClass)), virtualMethodInfo))); Assert.That(func(new BaseClass()), Is.EqualTo("base")); Assert.That(func(new DerivedClass()), Is.EqualTo("derived")); }
public void Should_call_struct_instance_method_via_parameter() { var func = CreateFunc <Counter, Counter>( Expr.Call(Expr.Parameter(0, typeof(Counter)), typeof(Counter).GetMethod("Count")), Expr.Return(Expr.Parameter(0, typeof(Counter)))); Assert.That(func(new Counter()).Value, Is.EqualTo(1)); }
public void Should_allow_hierarchy_conversion_for_instance() { MethodInfo methodInfo = typeof(BaseClass).GetMethod("Foo"); var func = CreateFunc <DerivedClass, string>(Expr.Return(Expr.Call(Expr.Parameter(0, typeof(DerivedClass)), methodInfo))); Assert.That(func(new DerivedClass { Result = "hi" }), Is.EqualTo("hi")); }
public void Should_call_struct_instance_method_via_field() { var func = CreateAction <CounterHolder>(Expr.Call( Expr.ReadField(Expr.Parameter(0, typeof(CounterHolder)), typeof(CounterHolder).GetField("Counter")), typeof(Counter).GetMethod("Count"))); var holder = new CounterHolder(); func(holder); Assert.That(holder.Counter.Value, Is.EqualTo(1)); }
public void Should_call_struct_instance_method_via_local_variable() { var local = Expr.LocalVariable(typeof(Counter), "s"); var func = CreateFunc <Counter, Counter>( Expr.DeclareLocal(local, Expr.Parameter(0, typeof(Counter))), Expr.Call(Expr.ReadLocal(local), typeof(Counter).GetMethod("Count")), Expr.Return(Expr.ReadLocal(local))); Assert.That(func(new Counter()).Value, Is.EqualTo(1)); }
private void AssertCounter <T>(T value, bool expectedResult) { var func = CreateAction <T, Counter>(Expr.IfThen( Expr.Parameter(0, typeof(T)), Expr.Call(Expr.Parameter(1, typeof(Counter)), typeof(Counter).GetMethod("Count")))); var counter = new Counter(); func(value, counter); Assert.That(counter.Value, Is.EqualTo(expectedResult ? 1 : 0)); }
public void Should_execute_all_statements_in_block() { var addMethod = typeof(Counter).GetMethod("Add"); var func = CreateAction <Counter>(Expr.Block( Expr.Call(Expr.Parameter(0, typeof(Counter)), addMethod), Expr.Call(Expr.Parameter(0, typeof(Counter)), addMethod))); var cnt = new Counter(); func(cnt); Assert.That(cnt.Value, Is.EqualTo(2)); }
public void Should_catch_exceptions() { var builder = new StringBuilder(); Func <char, StringBuilder> appendFn = builder.Append; var argParam = Expr.Parameter(0, typeof(int)); var sbParam = Expr.Parameter(1, typeof(StringBuilder)); var func = CreateAction <int, StringBuilder>(Expr.TryCatchFinally( Expr.Block( Expr.IfThen(Expr.Equal(argParam, Expr.Constant(1)), Expr.Throw(Expr.New(typeof(InvalidOperationException)))), Expr.IfThen(Expr.Equal(argParam, Expr.Constant(2)), Expr.Throw(Expr.New(typeof(ArgumentNullException)))), Expr.IfThen(Expr.Equal(argParam, Expr.Constant(3)), Expr.Throw(Expr.New(typeof(ArgumentException)))), Expr.IfThen(Expr.Equal(argParam, Expr.Constant(4)), Expr.Throw(Expr.New(typeof(ArithmeticException)))), Expr.Call(sbParam, appendFn.Method, ConstChar('X')) ), Expr.Call(sbParam, appendFn.Method, ConstChar('F')), new CatchBlock(typeof(InvalidOperationException), Expr.Call(sbParam, appendFn.Method, ConstChar('I'))), new CatchBlock(typeof(ArgumentNullException), Expr.Block(Expr.Call(sbParam, appendFn.Method, ConstChar('N')), Expr.Rethrow())), new CatchBlock(typeof(ArgumentException), Expr.Call(sbParam, appendFn.Method, ConstChar('A'))), new CatchBlock(Expr.Call(sbParam, appendFn.Method, ConstChar('D'))))); func(0, builder.Clear()); Assert.That(builder.ToString(), Is.EqualTo("XF")); func(1, builder.Clear()); Assert.That(builder.ToString(), Is.EqualTo("IF")); func(3, builder.Clear()); Assert.That(builder.ToString(), Is.EqualTo("AF")); func(4, builder.Clear()); Assert.That(builder.ToString(), Is.EqualTo("DF")); Assert.Throws <ArgumentNullException>(() => func(2, builder.Clear())); Assert.That(builder.ToString(), Is.EqualTo("NF")); }
public void Should_not_allow_not_null_instance_for_static_method() { var ex = Assert.Throws <ArgumentException>(() => Expr.Call(Expr.Constant(21), _parseInfo, Expr.Constant("22"))); Assert.That(ex.Message, Is.StringContaining("Static method cannot be called with instance parameter")); }
public void Should_not_allow_null_expression_array() { var ex = Assert.Throws <ArgumentNullException>(() => Expr.Call(_toStringInfo, null)); Assert.That(ex.Message, Is.StringContaining("arguments")); }
public void Should_not_allow_null_methodInfo() { var ex = Assert.Throws <ArgumentNullException>(() => Expr.Call(null)); Assert.That(ex.Message, Is.StringContaining("methodInfo")); }
public void Should_not_allow_null_instance_for_non_static_method() { var ex = Assert.Throws <ArgumentNullException>(() => Expr.Call(null, _toStringInfo)); Assert.That(ex.Message, Is.StringContaining("instance")); }
public void VoidMethodTypeTest() { Assert.That(Expr.Call(_fooInfo).ExpressionType, Is.EqualTo(typeof(void))); }
public void NonVoidMethodTypeTest() { Assert.That(Expr.Call(_formatInfo, Expr.Constant("{0}"), Expr.Convert(Expr.Constant(1), typeof(object))).ExpressionType, Is.EqualTo(typeof(string))); }
public void Should_not_allow_exceeding_number_of_method_parameters() { var ex = Assert.Throws <ArgumentException>(() => Expr.Call(_fooInfo, Expr.Constant(1))); Assert.That(ex.Message, Is.StringContaining("Invalid amount of parameters supplied to method: Void Foo()")); }
/// <summary> /// Compiles methods to access the data required for the DML operation /// </summary> /// <param name="mappings">The mappings of attribute name to source column</param> /// <param name="schema">The schema of data source</param> /// <param name="attributes">The attributes in the target metadata</param> /// <param name="dateTimeKind">The time zone that datetime values are supplied in</param> /// <returns></returns> protected Dictionary <string, Func <Entity, object> > CompileColumnMappings(EntityMetadata metadata, IDictionary <string, string> mappings, INodeSchema schema, IDictionary <string, AttributeMetadata> attributes, DateTimeKind dateTimeKind) { var attributeAccessors = new Dictionary <string, Func <Entity, object> >(); var entityParam = Expression.Parameter(typeof(Entity)); foreach (var mapping in mappings) { var sourceColumnName = mapping.Value; var destAttributeName = mapping.Key; if (!schema.ContainsColumn(sourceColumnName, out sourceColumnName)) { throw new QueryExecutionException($"Missing source column {mapping.Value}") { Node = this } } ; // We might be using a virtual ___type attribute that has a different name in the metadata. We can safely // ignore these attributes - the attribute names have already been validated in the ExecutionPlanBuilder if (!attributes.TryGetValue(destAttributeName, out var attr) || attr.AttributeOf != null) { continue; } var sourceType = schema.Schema[sourceColumnName]; var destType = attr.GetAttributeType(); var destSqlType = SqlTypeConverter.NetToSqlType(destType); var expr = (Expression)Expression.Property(entityParam, typeof(Entity).GetCustomAttribute <DefaultMemberAttribute>().MemberName, Expression.Constant(sourceColumnName)); var originalExpr = expr; if (sourceType == typeof(object)) { // null literal expr = Expression.Constant(null, destType); expr = Expr.Box(expr); } else { expr = SqlTypeConverter.Convert(expr, sourceType); expr = SqlTypeConverter.Convert(expr, destSqlType); var convertedExpr = SqlTypeConverter.Convert(expr, destType); if (attr is LookupAttributeMetadata lookupAttr && lookupAttr.AttributeType != AttributeTypeCode.PartyList) { // Special case: intersect attributes can be simple guids if (metadata.IsIntersect != true) { if (sourceType == typeof(SqlEntityReference)) { expr = SqlTypeConverter.Convert(originalExpr, sourceType); convertedExpr = SqlTypeConverter.Convert(expr, typeof(EntityReference)); } else { Expression targetExpr; if (lookupAttr.Targets.Length == 1) { targetExpr = Expression.Constant(lookupAttr.Targets[0]); } else { var sourceTargetColumnName = mappings[destAttributeName + "type"]; var sourceTargetType = schema.Schema[sourceTargetColumnName]; targetExpr = Expression.Property(entityParam, typeof(Entity).GetCustomAttribute <DefaultMemberAttribute>().MemberName, Expression.Constant(sourceTargetColumnName)); targetExpr = SqlTypeConverter.Convert(targetExpr, sourceTargetType); targetExpr = SqlTypeConverter.Convert(targetExpr, typeof(SqlString)); targetExpr = SqlTypeConverter.Convert(targetExpr, typeof(string)); } convertedExpr = Expression.New( typeof(EntityReference).GetConstructor(new[] { typeof(string), typeof(Guid) }), targetExpr, Expression.Convert(convertedExpr, typeof(Guid)) ); } destType = typeof(EntityReference); } } else if (attr is EnumAttributeMetadata && !(attr is MultiSelectPicklistAttributeMetadata)) { convertedExpr = Expression.New( typeof(OptionSetValue).GetConstructor(new[] { typeof(int) }), Expression.Convert(convertedExpr, typeof(int)) ); destType = typeof(OptionSetValue); } else if (attr is MoneyAttributeMetadata) { convertedExpr = Expression.New( typeof(Money).GetConstructor(new[] { typeof(decimal) }), Expression.Convert(expr, typeof(decimal)) ); destType = typeof(Money); } else if (attr is DateTimeAttributeMetadata) { convertedExpr = Expression.Convert( Expr.Call(() => DateTime.SpecifyKind(Expr.Arg <DateTime>(), Expr.Arg <DateTimeKind>()), expr, Expression.Constant(dateTimeKind) ), typeof(DateTime?) ); } // Check for null on the value BEFORE converting from the SQL to BCL type to avoid e.g. SqlDateTime.Null being converted to 1900-01-01 expr = Expression.Condition( SqlTypeConverter.NullCheck(expr), Expression.Constant(null, destType), convertedExpr); if (expr.Type.IsValueType) { expr = SqlTypeConverter.Convert(expr, typeof(object)); } } attributeAccessors[destAttributeName] = Expression.Lambda <Func <Entity, object> >(expr, entityParam).Compile(); }
public void Should_properly_map_parameters() { Func <int, char, string, long, bool, string> formatMethod = Format; var func = CreateFunc <int, char, string, long, bool, string>(Expr.Return(Expr.Call( formatMethod.Method, Expr.Parameter(0, typeof(int)), Expr.Parameter(1, typeof(char)), Expr.Parameter(2, typeof(string)), Expr.Parameter(3, typeof(long)), Expr.Parameter(4, typeof(bool))))); Assert.That(func(1, 'a', "text", -23, false), Is.EqualTo("1_a_text_-23_False")); }
static void Main(string[] args) { var asmName = "PlayGround.Generated"; var fileName = "PlayGround.Generated.dll"; var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(asmName), AssemblyBuilderAccess.RunAndSave); var modBuilder = asmBuilder.DefineDynamicModule(asmName, fileName, true); var typeBuilder = modBuilder.DefineType("PlayGround.Generated.MyClass", TypeAttributes.Class | TypeAttributes.Public); var fieldBuilder = typeBuilder.DefineField("field", typeof(string), FieldAttributes.InitOnly | FieldAttributes.Static | FieldAttributes.Public); var cb = typeBuilder.DefineTypeInitializer(); var builder = new MethodBodyBuilder(cb); builder.AddStatements( Expr.WriteField(fieldBuilder, Expr.Constant("abc")), Expr.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), Expr.Constant("Hello my friend!")), Expr.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string), typeof(object) }), Expr.Constant("What a {0} day!"), Expr.Constant("beautiful")), Expr.Call(typeof(Console).GetMethod("ReadKey", new Type[0]))); Console.WriteLine(builder.ToString()); builder.Compile(); var mb = typeBuilder.DefineMethod("foo", MethodAttributes.Public); mb.SetReturnType(typeof(string)); mb.SetParameters(typeof(int)); mb.DefineParameter(1, ParameterAttributes.None, "val"); builder = new MethodBodyBuilder(mb, typeof(int)); builder.AddStatements( Expr.IfThen(Expr.Parameter(1, typeof(int)), Expr.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), Expr.Constant("aha!"))), Expr.Return(Expr.Call( Expr.Call( Expr.New(typeof(StringBuilder)), typeof(StringBuilder).GetMethod("AppendFormat", new[] { typeof(string), typeof(object), typeof(object) }), Expr.Constant("{0}_{1}"), Expr.ReadField(fieldBuilder), Expr.Convert(Expr.Parameter(1, typeof(int)), typeof(object))), typeof(StringBuilder).GetMethod("ToString", new Type[0])))); Console.WriteLine(builder.ToString()); builder.Compile(); mb = typeBuilder.DefineMethod("bar", MethodAttributes.Public); mb.SetReturnType(typeof(string)); mb.SetParameters(typeof(string)); mb.DefineParameter(1, ParameterAttributes.None, "text"); builder = new MethodBodyBuilder(mb, typeof(string)); builder.AddStatements( Expr.Return( Expr.Call(typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object), typeof(object) }), Expr.Constant("Result: {0}-{1}"), Expr.IfThenElse( Expr.Parameter(1, typeof(string)), Expr.Call(typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object) }), Expr.Constant("Date: {0}"), Expr.Convert(Expr.Parameter(1, typeof(string)), typeof(object))), Expr.Constant("Undefined!")), Expr.Convert(Expr.Convert(Expr.Convert(Expr.Constant(16), typeof(object)), typeof(int)), typeof(object))) )); Console.WriteLine(builder.ToString()); builder.Compile(); mb = typeBuilder.DefineMethod("tryFinally", MethodAttributes.Public); mb.SetParameters(typeof(string)); mb.SetReturnType(typeof(void)); mb.DefineParameter(1, ParameterAttributes.None, "value"); builder = new MethodBodyBuilder(mb, typeof(string)); builder.AddStatements( Expr.TryFinally( Expr.IfThenElse(Expr.Parameter(1, typeof(string)), Expr.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), Expr.Parameter(1, typeof(string))), Expr.Throw(Expr.New(typeof(Exception), Expr.Constant("No string provided!")))), Expr.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), Expr.Constant("finally!"))) ); Console.WriteLine(builder.ToString()); builder.Compile(); mb = typeBuilder.DefineMethod("tryCatchFinally", MethodAttributes.Public); mb.SetParameters(typeof(string)); mb.SetReturnType(typeof(void)); mb.DefineParameter(1, ParameterAttributes.None, "value"); builder = new MethodBodyBuilder(mb, typeof(string)); var loc1 = Expr.LocalVariable(typeof(Exception), "e"); builder.AddStatements( Expr.TryCatchFinally( Expr.IfThenElse(Expr.Parameter(1, typeof(string)), Expr.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), Expr.Parameter(1, typeof(string))), Expr.Throw(Expr.New(typeof(ArgumentNullException), Expr.Constant("No string provided!")))), Expr.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), Expr.Constant("finally!")), new CatchBlock(typeof(ArgumentNullException), loc1, Expr.Rethrow()) )); Console.WriteLine(builder.ToString()); builder.Compile(); mb = typeBuilder.DefineMethod("localVar", MethodAttributes.Public); mb.SetReturnType(typeof(void)); var var1 = Expr.LocalVariable(typeof(string), "o"); var var2 = Expr.LocalVariable(typeof(int), "i"); builder = new MethodBodyBuilder(mb, typeof(string)); builder.AddStatements( Expr.DeclareLocal(var1, Expr.Constant("High {0}!")), Expr.DeclareLocal(var2, Expr.Constant(5)), Expr.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string), typeof(object) }), Expr.ReadLocal(var1), Expr.Convert(Expr.ReadLocal(var2), typeof(object)))); Console.WriteLine(builder.ToString()); builder.Compile(); mb = typeBuilder.DefineMethod("negNot", MethodAttributes.Public); mb.SetReturnType(typeof(int)); mb.SetParameters(typeof(byte)); builder = new MethodBodyBuilder(mb, typeof(byte)); builder.AddStatements(Expr.Return(Expr.Not(Expr.Negate(Expr.Parameter(1, typeof(byte)))))); Console.WriteLine(builder.ToString()); builder.Compile(); mb = typeBuilder.DefineMethod("loop", MethodAttributes.Public); mb.SetReturnType(typeof(void)); var iVar = Expr.LocalVariable(typeof(int), "i"); builder = new MethodBodyBuilder(mb); builder.AddStatements( Expr.DeclareLocal(iVar, Expr.Constant(10)), Expr.Loop(Expr.IfThenElse( Expr.ReadLocal(iVar), Expr.Block( Expr.WriteLocal(iVar, Expr.Add(Expr.ReadLocal(iVar), Expr.Constant(-1))), Expr.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), Expr.Constant("loop!..."))), Expr.LoopBreak())) ); Console.WriteLine(builder.ToString()); builder.Compile(); mb = typeBuilder.DefineMethod("conv", MethodAttributes.Public); mb.SetReturnType(typeof(ulong)); builder = new MethodBodyBuilder(mb); builder.AddStatements(Expr.Return(Expr.Convert(Expr.Constant(-1), typeof(ulong)))); Console.WriteLine(builder.ToString()); builder.Compile(); mb = typeBuilder.DefineMethod("intTS", MethodAttributes.Public); mb.SetReturnType(typeof(string)); builder = new MethodBodyBuilder(mb); builder.AddStatements(Expr.Return(Expr.Call(Expr.Constant(21), typeof(int).GetMethod("ToString", new Type[0])))); Console.WriteLine(builder.ToString()); builder.Compile(); mb = typeBuilder.DefineMethod("loadStructField", MethodAttributes.Public); mb.SetParameters(typeof(MyStruct)); mb.SetReturnType(typeof(string)); builder = new MethodBodyBuilder(mb, typeof(MyStruct)); builder.AddStatements(Expr.Return(Expr.ReadField(Expr.Parameter(1, typeof(MyStruct)), typeof(MyStruct).GetField("MyField")))); Console.WriteLine(builder.ToString()); builder.Compile(); mb = typeBuilder.DefineMethod("saveStructField", MethodAttributes.Public); mb.SetParameters(typeof(MyStruct), typeof(string)); mb.SetReturnType(typeof(MyStruct)); builder = new MethodBodyBuilder(mb, typeof(MyStruct), typeof(string)); builder.AddStatements( Expr.WriteField(Expr.Parameter(1, typeof(MyStruct)), typeof(MyStruct).GetField("MyField"), Expr.Parameter(2, typeof(string))), Expr.Return(Expr.Parameter(1, typeof(MyStruct)))); Console.WriteLine(builder.ToString()); builder.Compile(); mb = typeBuilder.DefineMethod("createStruct", MethodAttributes.Public); mb.SetReturnType(typeof(MyStruct)); builder = new MethodBodyBuilder(mb, typeof(MyStruct), typeof(string)); builder.AddStatements(Expr.Return(Expr.New(typeof(MyStruct))));//, Expr.Constant(32L), Expr.Constant("abcd") Console.WriteLine(builder.ToString()); builder.Compile(); mb = typeBuilder.DefineMethod("catchException", MethodAttributes.Public); mb.SetReturnType(typeof(Exception)); builder = new MethodBodyBuilder(mb); var local = Expr.LocalVariable(typeof(Exception), "e"); builder.AddStatements( Expr.DeclareLocal(local), Expr.TryCatch( Expr.Throw(Expr.New(typeof(InvalidOperationException), Expr.Constant("abc"))), new CatchBlock(typeof(InvalidOperationException), local, false, Expr.Empty())), Expr.Return(Expr.ReadLocal(local))); Console.WriteLine(builder.ToString()); builder.Compile(); typeBuilder.CreateType(); asmBuilder.Save(fileName); }
public void Should_call_struct_instance_method() { var func = CreateFunc <string>(Expr.Return(Expr.Call(Expr.Constant(21), _toStringInfo))); Assert.That(func(), Is.EqualTo("21")); }
public void Should_not_allow_insufficient_number_of_method_parameters() { var ex = Assert.Throws <ArgumentException>(() => Expr.Call(_formatInfo)); Assert.That(ex.Message, Is.StringContaining("Invalid amount of parameters supplied to method: System.String Format(System.String, System.Object)")); }
public void Should_allow_hierarchy_conversion_for_parameter() { var func = CreateFunc <string, string>(Expr.Return(Expr.Call(_formatInfo, Expr.Constant("Hello {0}!"), Expr.Parameter(0, typeof(string))))); Assert.That(func("world"), Is.EqualTo("Hello world!")); }
/// <summary> /// Produces the required expression to convert values to a specific type /// </summary> /// <param name="expr">The expression that generates the values to convert</param> /// <param name="to">The type to convert to</param> /// <returns>An expression to generate values of the required type</returns> public static Expression Convert(Expression expr, Type to) { if (expr.Type == typeof(SqlDateTime) && (to == typeof(SqlBoolean) || to == typeof(SqlByte) || to == typeof(SqlInt16) || to == typeof(SqlInt32) || to == typeof(SqlInt64) || to == typeof(SqlDecimal) || to == typeof(SqlSingle) || to == typeof(SqlDouble))) { expr = Expression.Condition( Expression.PropertyOrField(expr, nameof(SqlDateTime.IsNull)), Expression.Constant(SqlDouble.Null), Expression.Convert( Expression.PropertyOrField( Expression.Subtract( Expression.Convert(expr, typeof(DateTime)), Expression.Constant(SqlDateTime.MinValue) ), nameof(TimeSpan.TotalDays) ), typeof(SqlDouble) ) ); } if ((expr.Type == typeof(SqlBoolean) || expr.Type == typeof(SqlByte) || expr.Type == typeof(SqlInt16) || expr.Type == typeof(SqlInt32) || expr.Type == typeof(SqlInt64) || expr.Type == typeof(SqlDecimal) || expr.Type == typeof(SqlSingle) || expr.Type == typeof(SqlDouble)) && to == typeof(SqlDateTime)) { expr = Expression.Condition( NullCheck(expr), Expression.Constant(SqlDateTime.Null), Expression.Convert( Expression.Call( Expression.New( typeof(DateTime).GetConstructor(new[] { typeof(int), typeof(int), typeof(int) }), Expression.Constant(1900), Expression.Constant(1), Expression.Constant(1) ), typeof(DateTime).GetMethod(nameof(DateTime.MinValue.AddDays)), Expression.Convert( Expression.Convert(expr, typeof(SqlDouble)), typeof(double) ) ), typeof(SqlDateTime) ) ); } if (expr.Type == typeof(SqlString) && to == typeof(EntityCollection)) { expr = Expr.Call(() => ParseEntityCollection(Expr.Arg <SqlString>()), expr); } if (expr.Type == typeof(SqlString) && to == typeof(OptionSetValueCollection)) { expr = Expr.Call(() => ParseOptionSetValueCollection(Expr.Arg <SqlString>()), expr); } if (expr.Type != to) { if (expr.Type == typeof(object) && expr is ConstantExpression constant && constant.Value == null && typeof(INullable).IsAssignableFrom(to)) { return(Expression.Constant(GetNullValue(to))); } expr = Expression.Convert(expr, to); if (to == typeof(SqlString)) { expr = Expr.Call(() => UseDefaultCollation(Expr.Arg <SqlString>()), expr); } } return(expr); }
public void Should_not_allow_null_expression_in_array() { var ex = Assert.Throws <ArgumentNullException>(() => Expr.Call(_formatInfo, Expr.Constant("abs"), null)); Assert.That(ex.Message, Is.StringContaining("arguments[1]")); }
internal static Func <object, object> GetPropertyAccessor(PropertyInfo prop, Type targetType) { var rawParam = Expression.Parameter(typeof(object)); var param = SqlTypeConverter.Convert(rawParam, prop.DeclaringType); var value = (Expression)Expression.Property(param, prop); // Extract base value from complex types if (value.Type.IsGenericType && value.Type.GetGenericTypeDefinition() == typeof(Nullable <>)) { value = Expression.Property(value, nameof(Nullable <bool> .Value)); } if (typeof(OptionMetadata).IsAssignableFrom(value.Type)) { value = Expression.Property(value, nameof(OptionMetadata.Value)); } if (value.Type.BaseType != null && value.Type.BaseType.IsGenericType && value.Type.BaseType.GetGenericTypeDefinition() == typeof(ManagedProperty <>)) { value = Expression.Property(value, nameof(ManagedProperty <bool> .Value)); } if (value.Type.BaseType != null && value.Type.BaseType.IsGenericType && value.Type.BaseType.GetGenericTypeDefinition() == typeof(ConstantsBase <>)) { value = Expression.Property(value, nameof(ConstantsBase <bool> .Value)); } if (value.Type.IsArray) { value = Expr.Call(() => String.Join(Expr.Arg <string>(), Expr.Arg <object[]>()), Expression.Constant(","), value); } if (value.Type == typeof(Label)) { value = Expression.Property(value, nameof(Label.UserLocalizedLabel)); } if (value.Type == typeof(LocalizedLabel)) { value = Expression.Condition(Expression.Equal(value, Expression.Constant(null)), SqlTypeConverter.Convert(Expression.Constant(null), typeof(string)), Expression.Property(value, nameof(LocalizedLabel.Label))); } if (value.Type.IsEnum) { value = Expression.Call(value, nameof(Enum.ToString), Array.Empty <Type>()); } if (typeof(MetadataBase).IsAssignableFrom(value.Type)) { value = Expression.Condition(Expression.Equal(value, Expression.Constant(null)), SqlTypeConverter.Convert(Expression.Constant(null), typeof(Guid?)), Expression.Property(value, nameof(MetadataBase.MetadataId))); } var directConversionType = SqlTypeConverter.NetToSqlType(value.Type); if (directConversionType == typeof(SqlString) && value.Type != typeof(string)) { value = Expression.Call(value, nameof(Object.ToString), Array.Empty <Type>()); } var converted = SqlTypeConverter.Convert(value, directConversionType); if (targetType != directConversionType) { converted = SqlTypeConverter.Convert(converted, targetType); } // Return null literal if final value is null if (!value.Type.IsValueType) { value = Expression.Condition(Expression.Equal(value, Expression.Constant(null)), Expression.Constant(SqlTypeConverter.GetNullValue(targetType)), converted); } else { value = converted; } // Return null literal if original value is null if (!prop.PropertyType.IsValueType || prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable <>)) { value = Expression.Condition(Expression.Equal(Expression.Property(param, prop), Expression.Constant(null)), Expression.Constant(SqlTypeConverter.GetNullValue(targetType)), value); } // Compile the function value = Expr.Box(value); var func = (Func <object, object>)Expression.Lambda(value, rawParam).Compile(); return(func); }
public void Should_not_allow_implicit_boxing_for_method_parameters() { var ex = Assert.Throws <ArgumentException>(() => Expr.Call(_formatInfo, Expr.Constant("{0}"), Expr.Constant(32))); Assert.That(ex.Message, Is.StringContaining("Parameter expression of type System.Int32 does not match to type: System.Object")); }