示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        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();
        }
示例#4
0
        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);
            });
        }