public void Convert_Method() { var source = AstBuildHelper.ReadMemberRV(AstBuildHelper.ReadArgumentRA(0, typeof(SourceObject)), typeof(SourceObject).GetProperty("Source")); var writer = AstBuildHelper.WriteMember(typeof(DestinationObject).GetProperty("Destination"), AstBuildHelper.ReadArgumentRA(1, typeof(DestinationObject)), source); var type = DynamicAssemblyManager.DefineMapperType("MyClassType"); var convertMethod = type.DefineMethod("Convert", MethodAttributes.Public | MethodAttributes.Static, null, new Type[]{typeof(SourceObject), typeof(DestinationObject)}); convertMethod.DefineParameter(1, ParameterAttributes.None, "source"); convertMethod.DefineParameter(2, ParameterAttributes.None, "destination"); var context = new CompilationContext(convertMethod.GetILGenerator()); writer.Compile(context); new AstReturnVoid().Compile(context); type.CreateType(); DynamicAssemblyManager.SaveAssembly(); var sourceObj = new SourceObject{Source = 10}; var destinationObj = new DestinationObject(); object dynamicType = Activator.CreateInstance(type, false); type.InvokeMember("Convert", BindingFlags.InvokeMethod, null, dynamicType, new object[]{sourceObj, destinationObj}); Assert.AreEqual(sourceObj.Source, destinationObj.Destination); }
public void Convert_WithDelegate() { var type = DynamicAssemblyManager.DefineMapperType("MyClassType"); var field = type.DefineField("Lambda", typeof(Func<int>), FieldAttributes.Static | FieldAttributes.Public); Func<int> getValue = () => 10; var source = AstBuildHelper.CallMethod(field.FieldType.GetMethod("Invoke", new Type[0]), AstBuildHelper.ReadFieldRA(null, type.GetField("Lambda")), new List<IAstStackItem>()); var writer = AstBuildHelper.WriteMember(typeof(DestinationObject).GetProperty("Destination"), AstBuildHelper.ReadArgumentRA(1, typeof(DestinationObject)), source); var convertMethod = type.DefineMethod("ConvertLambda", MethodAttributes.Public | MethodAttributes.Static, null, new Type[]{typeof(SourceObject), typeof(DestinationObject)}); convertMethod.DefineParameter(1, ParameterAttributes.None, "source"); convertMethod.DefineParameter(2, ParameterAttributes.None, "destination"); var context = new CompilationContext(convertMethod.GetILGenerator()); writer.Compile(context); new AstReturnVoid().Compile(context); type.CreateType(); DynamicAssemblyManager.SaveAssembly(); var destinationObj = new DestinationObject(); object dynamicType = Activator.CreateInstance(type, false); type.GetField("Lambda").SetValue(dynamicType, getValue); type.InvokeMember("ConvertLambda", BindingFlags.InvokeMethod, null, dynamicType, new object[]{null, destinationObj}); Assert.AreEqual(10, destinationObj.Destination); }
public void Create_IfNull() { var type = DynamicAssemblyManager.DefineMapperType("MyClassType"); var convertMethod = type.DefineMethod("Create_IfNull", MethodAttributes.Public, null, new []{typeof(SourceObject), typeof(DestinationObject), typeof(IResourceMapper<object>), typeof(object)}); convertMethod.DefineParameter(1, ParameterAttributes.None, "source"); convertMethod.DefineParameter(2, ParameterAttributes.None, "destination"); convertMethod.DefineParameter(3, ParameterAttributes.None, "mapper"); convertMethod.DefineParameter(4, ParameterAttributes.None, "context"); var context = new CompilationContext(convertMethod.GetILGenerator()); new AstWriteArgument(1, typeof(DestinationObject), new AstIfNull( (IAstRef)AstBuildHelper.ReadArgumentRA(1, typeof(DestinationObject)), new AstNewObject(typeof(DestinationObject), new IAstStackItem[0]))) .Compile(context); new AstReturnVoid().Compile(context); type.CreateType(); DynamicAssemblyManager.SaveAssembly(); }
public override MapperAction <TContext> BuildAction <TFrom, TTo>(IMappingCollection <TFrom, TTo, TContext> map) { ExportMapInformation(map); var convertMethod = GetOrCreateConvertor(typeof(TFrom), typeof(TTo)); var context = new CompilationContext(convertMethod.GetILGenerator()); new AstWriteArgument(1, typeof(TTo), new AstIfNull( (IAstRef)AstBuildHelper.ReadArgumentRA(1, typeof(TTo)), AstBuildHelper.CastClass(AstBuildHelper.CallMethod(GetConstructOrThrowMethod(), AstBuildHelper.ReadFieldRA(null, _mapperField), new List <IAstStackItem> { new AstTypeof { type = typeof(TTo) } }), typeof(TTo)) )).Compile(context); if (map.UpdatesContext) { var funcField = _type.DefineField(GetFieldName <TFrom, TTo>(), typeof(Func <object, object, TContext, TContext>), FieldAttributes.Public | FieldAttributes.Static); _constructorValues.Add(funcField.Name, map.ContextUpdater); // var sourceFuncRoot = setter.SourceRoot.Length > 0 ? // AstBuildHelper.ReadMembersChain(AstBuildHelper.ReadArgumentRA(0, typeof(TFrom)), setter.SourceRoot) // : AstBuildHelper.ReadArgumentRV(0, typeof(TFrom)); var method = funcField.FieldType.GetMethod("Invoke", new [] { typeof(object), typeof(object), typeof(TContext) }); var contextUpdater = AstBuildHelper.CallMethod( method, AstBuildHelper.ReadFieldRA(null, funcField), new List <IAstStackItem> { AstBuildHelper.ReadArgumentRV(0, typeof(TFrom)), AstBuildHelper.ReadArgumentRA(1, typeof(TTo)), AstBuildHelper.ReadArgumentRA(2, typeof(TContext)) }); new AstWriteArgument(2, typeof(TContext), contextUpdater).Compile(context); } foreach (var iteratingSetter in map.Setters.Where(s => !s.IsIgnored)) { var setter = iteratingSetter; if (setter.Remap) { _mapper.RequireOneWayMap(setter.SourceType, setter.DestinationType, typeof(TFrom), typeof(TTo)); } switch (setter.SourceObjectType) { case MemberEntryType.Function: var funcField = _type.DefineField(GetFieldName <TFrom, TTo>(), setter.SourceFunc.GetType(), FieldAttributes.Public | FieldAttributes.Static); _constructorValues.Add(funcField.Name, setter.SourceFunc); // var sourceFuncRoot = setter.SourceRoot.Length > 0 ? // AstBuildHelper.ReadMembersChain(AstBuildHelper.ReadArgumentRA(0, typeof(TFrom)), setter.SourceRoot) // : AstBuildHelper.ReadArgumentRV(0, typeof(TFrom)); var method = funcField.FieldType.GetMethod("Invoke", new [] { typeof(object), typeof(object), typeof(TContext) }); var sourceFunc = AstBuildHelper.CallMethod( method, AstBuildHelper.ReadFieldRA(null, funcField), new List <IAstStackItem> { AstBuildHelper.ReadArgumentRV(0, typeof(TFrom)), AstBuildHelper.ReadArgumentRA(1, typeof(TTo)), AstBuildHelper.ReadArgumentRA(2, typeof(TContext)) }); if (setter.Remap) { var remapper = GetOrCreateMapper(setter.SourceType, setter.DestinationType); var remapMethod = AstBuildHelper.CallMethod(GetConvertMethod(setter.SourceType, setter.DestinationType), AstBuildHelper.ReadFieldRA(null, remapper), new List <IAstStackItem> { sourceFunc, AstBuildHelper.ReadMembersChain(AstBuildHelper.ReadArgumentRA(1, typeof(TTo)), setter.DestinationMember), AstBuildHelper.ReadArgumentRA(2, typeof(TContext)), }); var destination = AstBuildHelper.WriteMembersChain(setter.DestinationMember, AstBuildHelper.ReadArgumentRA(1, typeof(TTo)), remapMethod); destination.Compile(context); } else { var destination = AstBuildHelper.WriteMembersChain(setter.DestinationMember, AstBuildHelper.ReadArgumentRA(1, typeof(TTo)), sourceFunc); destination.Compile(context); } break; case MemberEntryType.Member: var sourceMember = AstBuildHelper.ReadMembersChain(AstBuildHelper.ReadArgumentRA(0, typeof(TFrom)), setter.SourceRoot.Union(setter.SourceMember).ToArray()); if (setter.Remap) { var remapper = GetOrCreateMapper(setter.SourceType, setter.DestinationType); var remapMethod = AstBuildHelper.CallMethod(GetConvertMethod(setter.SourceType, setter.DestinationType), AstBuildHelper.ReadFieldRA(null, remapper), new List <IAstStackItem> { sourceMember, AstBuildHelper.ReadMembersChain(AstBuildHelper.ReadArgumentRA(1, typeof(TTo)), setter.DestinationMember), AstBuildHelper.ReadArgumentRA(2, typeof(TContext)), }); var destination = AstBuildHelper.WriteMembersChain(setter.DestinationMember, AstBuildHelper.ReadArgumentRA(1, typeof(TTo)), remapMethod); destination.Compile(context); } else { var destination = AstBuildHelper.WriteMembersChain(setter.DestinationMember, AstBuildHelper.ReadArgumentRA(1, typeof(TTo)), sourceMember); destination.Compile(context); } break; default: throw new ArgumentOutOfRangeException(setter.SourceObjectType.ToString(), "MemberEntryType not supported"); } } new AstReturn { returnValue = AstBuildHelper.ReadArgumentRV(1, typeof(TTo)), returnType = typeof(TTo) }.Compile(context); var name = convertMethod.Name; Func <TFrom, TTo, TContext, TTo> converter = null; return((from, to, contxt) => { if (converter == null) { converter = (Func <TFrom, TTo, TContext, TTo>)Delegate.CreateDelegate( typeof(Func <TFrom, TTo, TContext, TTo>), null, _type.GetMethod(name)); } return converter((TFrom)from, (TTo)to, (TContext)contxt); }); }