.net 反射以在WCF中生成DTO对象
我想知道我是否能从WCF服务中反射和DTO对象的其他体验中找出性能上的差异。下面是我使用Linq从实体对象创建DTO对象的代码.net 反射以在WCF中生成DTO对象,.net,performance,entity-framework,reflection,dto,.net,Performance,Entity Framework,Reflection,Dto,我想知道我是否能从WCF服务中反射和DTO对象的其他体验中找出性能上的差异。下面是我使用Linq从实体对象创建DTO对象的代码 using (dashEntities context = new dashEntities()) { result = context.GetAlerts().Select(m => new AlertItemDTO() { }).ToList(); 另一个程序员在
using (dashEntities context = new dashEntities())
{
result = context.GetAlerts().Select(m => new AlertItemDTO()
{
}).ToList();
另一个程序员在构建其WCF服务时编写了一个通用方法,使用反射进行相同的转换:
private object TransferEntityToDTO(object dto, object entity)
{
Type entityType = entity.GetType();
// Use reflection to get all properties
foreach (PropertyInfo propertyInfo in entityType.GetProperties())
{
if (propertyInfo.CanRead)
{
List<PropertyInfo> dtoProperties = dto.GetType().GetProperties().ToList();
foreach (PropertyInfo dtoProperty in dtoProperties)
{
if (dtoProperty.Name == propertyInfo.Name)
{
object value = propertyInfo.GetValue(entity, null);
if (value != null && value.ToString() != "" && value.ToString() != "1/1/0001 12:00:00 AM")
{
// This section gets the type of of the property and casts
// to it during runtime then sets it to the corresponding
// dto value:
// Get current class type
Type currentClassType = this.GetType();
//Get type of property in entity object
Type propertyType = Type.GetType(propertyInfo.PropertyType.FullName);
// Get the Cast<T> method and define the type
MethodInfo castMethod = currentClassType.GetMethod("Cast").MakeGenericMethod(propertyType);
// Invoke the method giving value its true type
object castedObject = castMethod.Invoke(null, new object[] { value });
dtoProperty.SetValue(dto, value, null);
}
break;
}
}
}
}
return dto;
}
/// <summary>
/// Used in TransferEntityToDTO to dynamically cast objects to
/// their correct types.
/// </summary>
/// <typeparam name="T">Type to cast object to</typeparam>
/// <param name="o">Object to be casted</param>
/// <returns>Object casted to correct type</returns>
public static T Cast<T>(object o)
{
return (T)o;
}
private object transferentityToToToTo(对象dto,对象实体)
{
类型entityType=entity.GetType();
//使用反射获取所有属性
foreach(entityType.GetProperties()中的PropertyInfo PropertyInfo)
{
if(propertyInfo.CanRead)
{
List dtoProperties=dto.GetType().GetProperties().ToList();
foreach(数据属性中的数据属性信息)
{
if(dtoProperty.Name==propertyInfo.Name)
{
对象值=propertyInfo.GetValue(实体,空);
如果(value!=null&&value.ToString()!=“”&&value.ToString()!=“1/1/0001 12:00:00 AM”)
{
//此部分获取属性的类型并强制转换
//然后将其设置为相应的
//dto值:
//获取当前类类型
类型currentClassType=this.GetType();
//获取实体对象中的属性类型
Type propertyType=Type.GetType(propertyInfo.propertyType.FullName);
//获取Cast方法并定义类型
MethodInfo castMethod=currentClassType.GetMethod(“Cast”).MakeGenericMethod(propertyType);
//调用为值指定其真实类型的方法
object castedObject=castMethod.Invoke(null,新对象[]{value});
设置值(dto,value,null);
}
打破
}
}
}
}
返回dto;
}
///
///在TransferentityToToTo中用于将对象动态强制转换到
///他们的类型是正确的。
///
///要将对象强制转换到的类型
///要浇铸的对象
///将对象强制转换为正确的类型
公共静态T转换(对象o)
{
返回(T)o;
}
显然,第二种技术更难阅读,也更冗长,但它更通用,可以用于多种服务
我的问题是,使其通用化的能力是否超过了使用反射对性能的影响?如果不是,为什么?我发现了很多让人困惑的文章和答案,来解释反射的代价。我假设部分原因是因为它需要在不知道的情况下查找它所需的对象,就像在知道将要得到的异常时对所有对象使用通用异常一样
有人能帮我解释一下吗。谢谢如果您查看一些流行的开源映射库,如AutoMapper、EmitMapper或ValueInjector,您会发现它们不再使用反射方法,而是使用以下内容 显然,这使得它们在内部比基本的基于反射的映射器更复杂(它们仍然很容易使用),但像往常一样,优化速度会增加复杂性
我的意见是,您应该使用这些(优秀的)开源库中的一个,在这些库中,作者花了大量时间考虑了许多与您一样的问题。如果您查看一些流行的开源映射库,如AutoMapper、EmitMapper或ValueInjector,您会发现它们不再使用反射方法,相反,他们使用类似的东西 显然,这使得它们在内部比基本的基于反射的映射器更复杂(它们仍然很容易使用),但像往常一样,优化速度会增加复杂性
我的意见是,您应该使用这些(优秀的)开源库中的一个,在这些库中,作者花了大量时间考虑了许多与您一样的问题。也许一些轻量级的ORM会有所帮助。例如或。
他们可以使用IL(Emit)将SQL查询结果绑定到动态或静态对象。也许一些轻量级的ORM会有所帮助。例如或。
它们可以使用IL(Emit)将SQL查询的结果绑定到动态或静态对象。这两种解决方案的主要区别在于,第一种解决方案使用投影,第二种解决方案映射原始实体。对于仅为原始实体的一小部分的实体(例如列表的dto),仅查询投影属性而不是完整实体(可能具有嵌套实体和不需要的属性…)应该总是更快,然后将其映射到dto 要结合两种解决方案(投影+通用解决方案)的优点,您可以自动创建投影表达式,缓存它们,并在Select(表达式)调用中使用它们,就像在原始解决方案中一样。所以所有映射只创建一次,直接获取DTO,只查询必要的列。看看这篇文章和评论: AutoMapper也可以构建映射表达式,但它只映射简单的属性(据我从源代码中了解)。通过自定义解决方案和一些“表达式魔术”,您还可以支持复杂的映射,然后通过实体框架将这些映射转换为sql:
ContactName = Contact.Name,
AddressStreetAndNumber = (Address.Street + (" " + Address.Number)).Trim()
这段代码是一个很好的起点。这两种解决方案之间的主要区别在于,第一种解决方案使用投影,第二种解决方案映射原始实体。对于仅为原始实体的一小部分的实体(例如列表的DTO),只查询项目应该总是更快