private Action <TTarget, TSrc> CreateExpression(IEnumerable <string> fields) { var t1param = EE.Param <TTarget>("left"); var t2param = EE.Param <TSrc>("right"); var assignList = fields.Select(f => { var propA = typeof(TTarget).GetProperty(f); var propB = typeof(TSrc).GetProperty(f); if (propA.PropertyType == propB.PropertyType) { return(Expression.Assign(t1param.Dot(f), t2param.Dot(f))); } else if (propA.PropertyType == typeof(int) && propB.PropertyType.IsEnum || propB.PropertyType == typeof(int) && propA.PropertyType.IsEnum) { return(Expression.Assign(t1param.Dot(f), Expression.Convert(t2param.Dot(f), propA.PropertyType))); } else if (Nullable.GetUnderlyingType(propB.PropertyType) == propA.PropertyType || Nullable.GetUnderlyingType(propA.PropertyType) == propB.PropertyType) { return(Expression.Assign(t1param.Dot(f), Expression.Convert(t2param.Dot(f), propA.PropertyType))); } throw new InvalidOperationException($"Invalid operation, cannot copy {propB} to {propA}."); }); //var resultArr = Expression.NewArrayInit(typeof(bool), cmplist); var block = Expression.Block(assignList); var l = Expression.Lambda <Action <TTarget, TSrc> >(block, t1param, t2param); return(l.Compile()); }
private Func <T1, TVal[]> CreateExpression(IEnumerable <string> fields) { var t1param = EE.Param <T1>("obj"); var elist = fields.Select(f => t1param.Dot(f)).Cast <Expression>(); if (typeof(TVal) == typeof(object)) { elist = elist.Select(e => EE.Box(e)); } var resultArr = Expression.NewArrayInit(typeof(TVal), elist); var l = Expression.Lambda <Func <T1, TVal[]> >(resultArr, t1param); return(l.Compile()); }
private Func <T1, T2, DifferReturnValueType[]> CreateExpression(IEnumerable <string> fields) { var t1param = EE.Param <T1>("left"); var t2param = EE.Param <T2>("right"); var NULL = EE.Val <DifferReturnValueType>(null); var TupleCreate = EE.Method(() => Tuple.Create <string, object>("", null)); var cmplist2 = fields.Select(f => Expression.Condition(t1param.Dot(f).IsEq(t2param.Dot(f)), NULL, Expression.Call(TupleCreate, EE.Val(f), EE.Box(t2param.Dot(f))))); var resultArr = Expression.NewArrayInit(typeof(DifferReturnValueType), cmplist2); var l = Expression.Lambda <Func <T1, T2, DifferReturnValueType[]> >(resultArr, t1param, t2param); return(l.Compile()); }
private Action <TTarget, TSrc> CreateExpression(IEnumerable <string> fields) { var targetParam = EE.Param <TTarget>("left"); var sourceParam = EE.Param <TSrc>("right"); IEnumerable <Expression> assignList = fields.Select(f => { var propTarget = typeof(TTarget).GetProperty(f); var propSource = typeof(TSrc).GetProperty(f); if (propTarget.PropertyType == propSource.PropertyType) { return(Expression.Assign(targetParam.Dot(f), sourceParam.Dot(f)) as Expression); } else if (propTarget.PropertyType == typeof(int) && propSource.PropertyType.IsEnum || propSource.PropertyType == typeof(int) && propTarget.PropertyType.IsEnum) { return(Expression.Assign(targetParam.Dot(f), Expression.Convert(sourceParam.Dot(f), propTarget.PropertyType))); } // assigning nullable to non-nullable creates prop = default(T) else if (Nullable.GetUnderlyingType(propSource.PropertyType) == propTarget.PropertyType) { var iffed = Expression.IfThenElse(sourceParam.Dot(f).NotNull(), Expression.Assign(targetParam.Dot(f), Expression.Convert(sourceParam.Dot(f), propTarget.PropertyType)), Expression.Assign(targetParam.Dot(f), Expression.Default(propTarget.PropertyType))); return(iffed); } // target is nullable, source is not - nothing special, it will never get null else if (Nullable.GetUnderlyingType(propTarget.PropertyType) == propSource.PropertyType) { return(Expression.Assign(targetParam.Dot(f), Expression.Convert(sourceParam.Dot(f), propTarget.PropertyType))); } throw new InvalidOperationException($"Invalid operation, cannot copy {propSource} to {propTarget}."); }); //var resultArr = Expression.NewArrayInit(typeof(bool), cmplist); var block = Expression.Block(assignList); var l = Expression.Lambda <Action <TTarget, TSrc> >(block, targetParam, sourceParam); return(l.Compile()); }
private Func <T1, int> CreateExpression(PropertyInfo[] fields, FieldHasherOptions options) { /* * $hash = 17; * $hash += $hash * 23 + .Call ($obj.a).GetHashCode(); * $hash += $hash * 23 + .Call ($obj.b).GetHashCode(); * .If ($obj.s != null) { * $hash += $hash * 23 + .Call (.Call ($obj.s).Trim()).GetHashCode() * } .Else { * $hash *= 23 * }; * $hash += $hash * 23 + .Call ($obj.date).GetHashCode(); * $hash += $hash * 23 + .Call ($obj.mynullable).GetHashCode(); * $hash */ const int prim = 17; const int prim2 = 23; var t1param = EE.Param <T1>("obj"); var resultHash = EE.Param <int>("hash"); var ass = Expression.Assign(resultHash, Expression.Constant(prim)); var block = new List <Expression>(); block.Add(ass); var returnLabel = Expression.Label(typeof(int)); var whenNull = options.ZeroIfNulls ? Expression.Return(returnLabel, Expression.Constant(0)) : resultHash.MulAssign(prim2); block.AddRange(fields.Select(pi => { var dotted = t1param.Dot(pi.Name); var propType = pi.PropertyType; var addAssignHashCode = Expression.AddAssign(resultHash, resultHash.Mul(prim2).Add(dotted.Call("GetHashCode"))); // nullable if (options.ZeroIfNulls && Nullable.GetUnderlyingType(propType) != null) { return(Expression.IfThenElse( dotted.NotNull(), addAssignHashCode, whenNull)); } // value type but not nullabl if (propType.IsValueType) { return((Expression)addAssignHashCode); } // normalized string var normalized = propType == typeof(string) && options.StringNormalizer != null ? options.StringNormalizer(dotted) : dotted; var iffed = Expression.IfThenElse(dotted.NotNull(), Expression.AddAssign(resultHash, resultHash.Mul(prim2).Add(normalized.Call("GetHashCode"))), whenNull); return(iffed); })); block.Add(Expression.Label(returnLabel, resultHash)); var eblock = Expression.Block(new [] { resultHash }, block); var l = Expression.Lambda <Func <T1, int> >(eblock, t1param); return(l.Compile()); }