Пример #1
0
        private static void AssertCopy(DtoCopierProperties dstType, DtoCopierProperties srcType)
        {
            if (dstType.InterfType == srcType.InterfType)
            {
                return;
            }

            if (dstType.GenericInterfType == srcType.GenericInterfType)
            {
                return;
            }

            throw new NotImplementedException($"Templates {dstType.PropertiesType.FullName} and {srcType.PropertiesType.FullName} are not compatible.");
        }
Пример #2
0
        /// <summary>
        /// Prepare a delegate which has method signature: void CopyMethod(DstType dst, SrcType src, HashSet/<string/> properties)<para/>
        /// The delegate can take properties NULL value. In the case it will do full copy.
        /// </summary>
        public Delegate GetCopyDelegate(Type dstType, Type dstTemplate, Type srcType, Type srcTemplate, bool excludePropertiesLogic)
        {
            Func <string, Delegate> get = null;

            get = xKey =>
            {
                var srcTypeProps = new DtoCopierProperties(srcType, srcTemplate);
                var dstTypeProps = new DtoCopierProperties(dstType, dstTemplate);

                var tKey = GetKey(dstTypeProps.PropertiesType, dstTemplate, srcTypeProps.PropertiesType, srcTemplate, excludePropertiesLogic);
                if (tKey != xKey)
                {
                    return(m_copiers.GetOrAdd(GetKey(dstTypeProps.PropertiesType, dstTemplate, srcTypeProps.PropertiesType, srcTemplate, excludePropertiesLogic), get));
                }

                return(CreateDelegate(dstTypeProps, srcTypeProps, excludePropertiesLogic));
            };

            return(m_copiers.GetOrAdd(GetKey(dstType, dstTemplate, srcType, srcTemplate, excludePropertiesLogic), get));
        }
Пример #3
0
        private BinaryExpression CreateAssign(DtoCopierProperties dstType, ParameterExpression dstParameter, PropertyInfo dstProperty, ParameterExpression srcParameter, PropertyInfo srcProperty)
        {
            Expression srcValue = Expression.Property(srcParameter, srcProperty);

            if (srcProperty.PropertyType != dstProperty.PropertyType)
            {
                var cast = m_casts?.Get(dstProperty.PropertyType, srcProperty.PropertyType, dstType.GenericInterfType);
                if (cast != null)
                {
                    srcValue = Expression.Call(cast, srcValue);
                }
                else
                {
                    srcValue = Expression.Convert(srcValue, dstProperty.PropertyType);
                }
            }

            return(Expression.Assign(
                       Expression.Property(dstParameter, dstProperty),
                       srcValue));
        }
Пример #4
0
        private Delegate CreateDelegate(DtoCopierProperties dstType, DtoCopierProperties srcType, bool exclude)
        {
            AssertCopy(dstType, srcType);

            var srcProperties = srcType.GetProperties().Where(x => x.CanRead && x.CanWrite).ToList();
            var dstProperties = new Dictionary <string, PropertyInfo>().Load(dstType.GetProperties(), x => x.Name);

            var srcPar        = Expression.Parameter(srcType.PropertiesType);
            var dstPar        = Expression.Parameter(dstType.PropertiesType);
            var propertiesPar = Expression.Parameter(typeof(HashSet <string>));

            var blockList = new List <Expression>();

            foreach (var srcProp in srcProperties)
            {
                var dstProp = dstProperties.Get(srcProp.Name);

                var assignProp = CreateAssign(dstType, dstPar, dstProp, srcPar, srcProp);

                blockList.Add(assignProp);
            }

            var updateBlockList = new List <Expression>();

            foreach (var srcProp in srcProperties)
            {
                var dstProp = dstProperties.Get(srcProp.Name);

                var assignProp = CreateAssign(dstType, dstPar, dstProp, srcPar, srcProp);

                Expression update;
                if (exclude)
                {
                    update =
                        Expression.IfThen(
                            Expression.Not(Expression.Call(propertiesPar, s_containsMethod, Expression.Constant(srcProp.Name))),
                            assignProp);
                }
                else
                {
                    update =
                        Expression.IfThen(
                            Expression.Call(propertiesPar, s_containsMethod, Expression.Constant(srcProp.Name)),
                            assignProp);
                }

                updateBlockList.Add(update);
            }

            if (!blockList.Any())
            {
                Action <object, object, object> stub = (x, y, z) => { };
                return(stub);
            }

            var body = Expression.IfThenElse(
                Expression.Equal(propertiesPar, Expression.Constant(null)),
                Expression.Block(blockList),
                Expression.Block(updateBlockList));

            return(Expression.Lambda(body, dstPar, srcPar, propertiesPar).Compile());
        }