现在做的项目原本是WCF+EF的,原本是把EF的类直接给WCF用的。现在需要分开,以便WCF类和EF类分别独立演化,因为前端和后端的人员不同,类设计习惯不同;而且有时候为了数据库表的设计,EF类无法直接给前端用。先不论这部分的设计思路对不对,在服务接口部分需要WCF类和EF类转换,因为基本是相同的类对象,除了一部分属性不同外,基本上属性是都相同的,就考虑用反射统一转换,当然,后续演化属性名很多不同的话,就会有问题。
总之,我要测试一下用反射动态拷贝和代码写死静态拷贝的效率差别,不用测试肯定也知道反射效率低,只是想看看差别多少。
两个类:
LocationCard,EF类,MVC中在页面上编辑的类
public class LocationCard:ITag
{
/// <summary>
/// 主键Id
/// </summary>
[Display(Name = "主键Id")]
public int Id { get; set; }
/// <summary>
/// 对接Id
/// </summary>
[Display(Name = "对接Id")]
public int? Abutment_Id { get; set; }
/// <summary>
/// 终端编号
/// </summary>
[Display(Name = "终端编号")]
[Required]
public string Code { get; set; }
/// <summary>
/// 终端名称
/// </summary>
[Display(Name = "终端名称")]
[Required]
public string Name { get; set; }
/// <summary>
/// 描述
/// </summary>
[Display(Name = "描述")]
public string Describe { get; set; }
public override string ToString()
{
return Name;
}
}
Tag WCF类 传输给前端用的类对象
public class Tag: ITag
{
public int Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Describe { get; set; }
public override string ToString()
{
return Name;
}
}
ITag的内容就是Tag中的那些属性
反射方式转换:
public static List<T2> ConvertObjectList<T1, T2>(this IList<T1> list) where T2 : class, new()
{
if (list == null) return null;
Stopwatch stopwatch=new Stopwatch();
stopwatch.Start();
Type type1 = typeof(T1);
Type type2 = typeof(T2);
//PropertyInfo[] propertyInfos1 = type1.GetProperties();
PropertyInfo[] propertyInfos2 = type2.GetProperties();
List<T2> listNew = new List<T2>();
foreach (T1 item in list)
{
//T2 itemNew = ConvertObjectTo<T1, T2>(item);
//listNew.Add(itemNew);
T2 obj2 = new T2();
try
{
foreach (PropertyInfo p2 in propertyInfos2)
{
try
{
PropertyInfo p1 = type1.GetProperty(p2.Name);
if (p1 == null) continue;
object value = p1.GetValue(item);
p2.SetValue(obj2, value);
}
catch (Exception ex)
{
LogEvent.Info(ex.ToString());
}
}
listNew.Add(obj2);
}
catch (Exception ex)
{
LogEvent.Info(ex.ToString());
}
}
stopwatch.Stop();
LogEvent.Info("ConvertObjectList Time:" + stopwatch.Elapsed);
return listNew;
}
静态代码方式转换
#region LocationCard <=> Tag
public static List<Tag> ToWcfModelList(this List<LocationCard> list1)
{
return list1.ToTModel().ToWCFList();
}
public static List<Tag> ToTModel(this List<LocationCard> list1)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
List<Tag> list2 = new List<Tag>();
foreach (var item1 in list1)
{
list2.Add(item1.ToModel());
}
stopwatch.Stop();
LogEvent.Info("ToTModel Of List Time:" + stopwatch.Elapsed);
return list2;
}
public static Tag ToModel(this LocationCard item1)
{
Tag item2 = new Tag();
item2.Id = item1.Id;
item2.Name = item1.Name;
item2.Code = item1.Code;
item2.Describe = item1.Describe;
return item2;
}
public static List<LocationCard> ToDbModel(this List<Tag> list1)
{
//return list1.ConvertObjectList<Tag, LocationCard>();
var list2 = new List<LocationCard>();
foreach (var item1 in list1)
{
list2.Add(item1.ToDbModel());
}
return list2;
}
public static LocationCard ToDbModel(this Tag item1)
{
LocationCard item2 = new LocationCard();
item2.Id = item1.Id;
item2.Name = item1.Name;
item2.Code = item1.Code;
item2.Describe = item1.Describe;
return item2;
}
#endregion
测试代码
class Program
{
static void Main(string[] args)
{
string input = "";
Console.WriteLine("Input Count:");
input = Console.ReadLine();
while (input.ToLower() != "q")
{
int count = int.Parse(input);
for (int i = 1; i < 10; i++)
{
TestByCount(count*i);
}
Console.WriteLine("Input Count:");
input = Console.ReadLine();
}
Console.WriteLine("Exit");
Console.Read();
}
private static void TestByCount(int count)
{
Console.WriteLine("Count:" + count);
List<LocationCard> cards = InitList(count);
List<Tag> tags = cards.ConvertObjectList<LocationCard, Tag>();
List<Tag> tags2 = cards.ToTModel();
Console.WriteLine();
}
private static List<LocationCard> InitList(int count)
{
List<LocationCard> cards = new List<LocationCard>();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < count; i++)
{
LocationCard card = new LocationCard();
card.Id = i;
card.Name = "Card" + i;
card.Code = "Code" + i;
card.Abutment_Id = i;
card.Describe = "Describe" + i;
//card.Id = i;
//card.Name = "Card";
//card.Code = "Code";
//card.Abutment_Id = i;
//card.Describe = "Describe";
cards.Add(card);
}
stopwatch.Stop();
LogEvent.Info("InitList Time:" + stopwatch.Elapsed);
return cards;
}
}
测试结果:
总之100万时反射需要2s多,而静态方法则0.2s则不到,满了13倍左右。
1w以下的小数量,相同属性可以考虑用反射方式,因为不用写代码!
好多类呢,写个工具自动生成转换代码吧。