使用其他类的属性值创建类的对象列表的扩展方法
本文关键字:对象 列表 方法 创建 扩展 属性 其他 | 更新日期: 2023-09-27 18:15:20
我为IQueryable类创建了一个Extension方法,用于将泛型源类的列表转换为其他泛型目标类的列表(.net3.5(
我正在使用反射从源对象值中获取属性,并将其分配给目标对象
该类的源代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;
namespace System.Linq
{
public static class QueryableExtensions
{
public static IQueryable<TDest> ToDTO<TDest>(this IQueryable<TSource> source)//getting error on this line
{
return DTOTranslator<TDest>.ConvertToDTO<TDest>(source);
}
}
public class DTOTranslator<TSource>
{
public static IQueryable<TDest> ConvertToDTO<TDest>(IQueryable<TSource> source)
{
List<TDest> destinationList = new List<TDest>();
List<TSource> sourceList = source.ToList<TSource>();
var sourceType = typeof(TSource);
var destType = typeof(TDest);
foreach (TSource sourceElement in sourceList)
{
TDest destElement = Activator.CreateInstance<TDest>();
//Get all properties from the object
PropertyInfo[] sourceProperties = typeof(TSource).GetProperties();
foreach (PropertyInfo sourceProperty in sourceProperties)
{
//and assign value to each propery according to property name.
PropertyInfo destProperty = destType.GetProperty(sourceProperty.Name);
destProperty.SetValue(destElement, sourceProperty.GetValue(sourceElement, null), null);
destinationList.Add(destElement);
}
}
return destinationList.AsQueryable();
}
}
}
然而,在编译时,我在第12行得到了错误:
The type or namespace name 'TSource' could not be found (are you missing a using directive or an assembly reference?)
更新:
感谢大家的回复。
现在我更新了我的课程如下:
public static class QueryableExtensions
{
public static IQueryable<TDest> ToDTO<TSource, TDest>(this IQueryable<TSource> source)
{
List<TDest> destinationList = new List<TDest>();
List<TSource> sourceList = source.ToList<TSource>();
var sourceType = typeof(TSource);
var destType = typeof(TDest);
foreach (TSource sourceElement in sourceList)
{
TDest destElement = Activator.CreateInstance<TDest>();
//Get all properties from the object
PropertyInfo[] sourceProperties = typeof(TSource).GetProperties();
foreach (PropertyInfo sourceProperty in sourceProperties)
{
//and assign value to each propery according to property name.
PropertyInfo destProperty = destType.GetProperty(sourceProperty.Name);
destProperty.SetValue(destElement, sourceProperty.GetValue(sourceElement, null), null);
destinationList.Add(destElement);
}
}
return destinationList.AsQueryable();
}
}
这很好,
现在我唯一想知道的是-
是否可以跳过CCD_ 1参数,
如何从IQueryable的元素类型中读取并定义其对象?我的意思是,目前我将该方法称为
IQueryable<CATEGORY_DTO> dtos = (from p in new MyEntities().CATEGORY select p).ToDTO<CATEGORY, CATEGORY_DTO>();
我想称之为
IQueryable<CATEGORY_DTO> dtos = (from p in new MyEntities().CATEGORY select p).ToDTO<CATEGORY_DTO>();
谢谢,NJ
试试这个:
public static class QueryableExtensions
{
public static IQueryable<TDest> ToDTO<TDest, TSource>(this IQueryable<TSource> source)
{
return DTOTranslator<TSource>.ConvertToDTO<TDest>(source);
}
}
另外,ToDTO
方法还引用了TSource
泛型类型(因为否则你怎么能引用它作为参数-这导致了最初的错误(,并且该泛型类型在DTOTranslator
的构造函数中给出(由于在构造函数中使用TDest
是错误的,因为构造函数本身中所需的泛型类型的定义是TSource
,这是与TDest
不同的类型(。
您需要声明两个类型参数:
public static IQueryable<TDest> ToDTO<TSource, TDest>(this IQueryable<TSource> source)
您应该按以下方式更改函数签名,并在转换器中稍作更改,我认为您不能传递源类型,否则您可以添加泛型参数作为函数的输入。
public static IQueryable<TDest> ToDTO<TDest>(this IQueryable source)
{
return DTOTranslator<TDest>.ConvertToDTO<TDest>(source);
}
public static IQueryable<TDest> ConvertToDTO<TDest>(IQueryable source)
{
Type sourceType = null;
....
foreach(var item in source)
{
// find source type is it not found till now
if (sourceType == null)
sourceType = item.GetType();
....
}
}
yaakov对您提出的问题的回答是正确的,因此我投了赞成票。不过,我认为还有更好的答案。
作为编写自己的映射反射代码的替代方案,可以考虑使用automapper。
http://automapper.org/
这是一个已经解决的问题,很多人都经过了很好的测试和使用,它有很多功能和灵活性,可以处理很多你可能没有考虑的边缘案例。我建议你去看看。
还想补充一点,使用system.linq命名空间有点奇怪。系统应该为框架类库中的东西保留,我建议您使用自己的名称空间。这并不重要,但我认为使用这样的东西会让您和代码的任何其他用户感到困惑。