因为公司使用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;
}
}
}
}