Ning's Blog

http://www.uniq.cn
05

因为公司使用WCF开发系统,要做两次转换,所以写了这个通用的转换代码,反射写的,性能较差,有待改进。

比如有个实体类ItemEntity,有个接口类ItemData,完成转换只需如下

ItemData data = CommonTransfer.ToTarget<ItemData,ItemEntity>(entity);

即可,要提供性能可以使用Emit自己写IL代码,这个太复杂不想研究了,还有个方法就是使用.NET 3.5的新特性,表达式树。有时间研究下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections;

namespace CommonTransfer
{
    public static class CommonTransfer<TTarget, TSource>
        where TTarget : class, new()
        where TSource : class, new()
    {
        public static TTarget ToTarget(TSource source)
        {
            return Transform(typeof(TTarget), typeof(TSource), source) as TTarget;
        }

        private static object Transform(Type targetType, Type sourceType, object propInfo)
        {
            Object result = targetType.GetConstructor(Type.EmptyTypes).Invoke(null);
            PropertyInfo[] propInfos = targetType.GetProperties();
            PropertyInfo[] sourcePropInfos = sourceType.GetProperties();
            for (int i = 0; i < propInfos.Length; i++)
            {
                PropertyInfo sourceProp = sourcePropInfos.FirstOrDefault(p => p.Name == propInfos[i].Name);
                if (sourceProp == null)
                {
                    throw new Exception(string.Format("{0} is not exist in source type", propInfos[i].Name));
                }
                object value = sourceProp.GetValue(propInfo, null);
                if (IsCollectionProperty(sourceProp) && value != null)
                {
                    MethodInfo addMethod = propInfos[i].PropertyType.GetMethod("Add");
                    object temp = null;
                    if (propInfos[i].PropertyType.GetGenericArguments()[0] == typeof(string))
                    {
                        temp = new List<string>();
                        foreach (string str in value as IList)
                        {
                            object[] strArray = { str };
                            addMethod.Invoke(temp, strArray);
                        }
                    }
                    else
                    {
                        temp = propInfos[i].PropertyType.GetConstructor(Type.EmptyTypes).Invoke(null);
                        foreach (var item in value as IList)
                        {
                            if (item != null)
                            {
                                object[] args = { Transform(propInfos[i].PropertyType.GetGenericArguments()[0], item.GetType(), item) };
                                addMethod.Invoke(temp, args);
                            }
                        }
                    }
                    propInfos[i].SetValue(result, temp, null);
                }
                else
                {
                    if (sourceProp != null
                        && sourceProp.PropertyType.IsClass
                        && sourceProp.PropertyType != typeof(string)
                        && value != null)
                    {
                        value = Transform(propInfos[i].PropertyType, sourceProp.PropertyType, value);
                    }
                    else
                    {
                        value = Convert.ChangeType(value, propInfos[i].PropertyType);
                    }
                    propInfos[i].SetValue(result, value, null);
                }

            }
            return result;
        }

        private static bool IsCollectionProperty(PropertyInfo propInfo)
        {
            if (Array.IndexOf(propInfo.PropertyType.GetInterfaces(), typeof(IList)) > -1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}

推荐(2)
收藏

随机本博客日志

发表评论: