Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将数据表转换为列表<;T>;_C# - Fatal编程技术网

C# 将数据表转换为列表<;T>;

C# 将数据表转换为列表<;T>;,c#,C#,有没有一种方法可以在不指定单个字段的情况下将数据表从转换为列表?更简洁?推断属性 public class Task { public int Id { get; set; } public string Name { get; set; } } public class TasksDAL { public static List<Task> GetTasks() { DataTable dt = GetTasksDT();

有没有一种方法可以在不指定单个字段的情况下将数据表从
转换为
列表
?更简洁?推断属性

public class Task
{
    public int Id { get; set; }
    public string Name { get; set; }
}


public class TasksDAL
{

    public static List<Task> GetTasks()
    {
        DataTable dt = GetTasksDT();
        List<Task> tasks = new List<Task>();
        tasks = (from DataRow row in dt.Rows
                 select new Task
                 {
                     Id = (int)row["Id"],
                     Name = row["Name"].ToString()
                 }).ToList();

        return tasks;
    }

}
公共类任务
{
公共int Id{get;set;}
公共字符串名称{get;set;}
}
公共类任务
{
公共静态列表GetTasks()
{
DataTable dt=GetTasksDT();
列表任务=新列表();
tasks=(来自dt.Rows中的DataRow行
选择新任务
{
Id=(int)行[“Id”],
名称=行[“名称”]。ToString()
}).ToList();
返回任务;
}
}

我有一段旧代码,它使用反射从数据表填充obj列表

列的名称必须与属性的名称相同

var result = dt.ToList<Task>()


  public static List<T> ToList<T>(this DataTable dt) where T : new()
        {
        var returnList = new List<T>();

        var properties = new PropertyInfo[dt.Columns.Count];

        for (int i = 0; i < properties.Length; i++)
        {
            properties[i] = typeof(T).GetProperty(dt.Columns[i].Caption, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
        }

        PropertyInfo property;

        foreach (DataRow dr in dt.Rows)
        {
            T resultItem = new T();

            for (int i = 0; i < properties.Length; i++)
            {
                if ((property = properties[i]) == null)
                {
                    continue;
                }

                if (!DBNull.Value.Equals((object)dr[i] ?? (object)DBNull.Value))
                {
                    property.SetValue(resultItem, dr[i], null);
                }
            }

            returnList.Add(resultItem);
        }

        return returnList;
    }
var result=dt.ToList()
公共静态列表ToList(此数据表dt),其中T:new()
{
var returnList=新列表();
var properties=newpropertyinfo[dt.Columns.Count];
for(int i=0;i
我更喜欢将
IEnumerable
返回到
列表
并以相反的方向反映,为所有属性和字段分配匹配的列名:

使用
MemberInfo
上的一些扩展来处理属性或字段:

public static object GetValue(this MemberInfo member, object srcObject) {
    if (member.MemberType == MemberTypes.Property)
        return ((PropertyInfo)member).GetValue(srcObject, null);
    else if (member.MemberType == MemberTypes.Field)
        return ((FieldInfo)member).GetValue(srcObject);
    else
        throw new Exception("Property must be of type FieldInfo or PropertyInfo");
}

public static void SetValue<T>(this MemberInfo member, object destObject, T value) {
    if (member.MemberType == MemberTypes.Property)
        ((PropertyInfo)member).SetValue(destObject, value);
    else if (member.MemberType == MemberTypes.Field)
        ((FieldInfo)member).SetValue(destObject, value);
    else
        throw new Exception("Property must be of type FieldInfo or PropertyInfo");
}

public static Type GetMemberType(this MemberInfo member) {
    switch (member.MemberType) {
        case MemberTypes.Field:
            return ((FieldInfo)member).FieldType;
        case MemberTypes.Property:
            return ((PropertyInfo)member).PropertyType;
        case MemberTypes.Event:
            return ((EventInfo)member).EventHandlerType;
        default:
            throw new ArgumentException("MemberInfo must be if type FieldInfo, PropertyInfo or EventInfo", "member");
    }
}
公共静态对象GetValue(此MemberInfo成员,对象srcObject){
if(member.MemberType==MemberTypes.Property)
return((PropertyInfo)成员).GetValue(srcObject,null);
else if(member.MemberType==MemberTypes.Field)
return((FieldInfo)成员).GetValue(srcObject);
其他的
抛出新异常(“属性必须为FieldInfo或PropertyInfo类型”);
}
公共静态void SetValue(此MemberInfo成员、对象destObject、T值){
if(member.MemberType==MemberTypes.Property)
((PropertyInfo)成员).SetValue(destObject,value);
else if(member.MemberType==MemberTypes.Field)
((FieldInfo)成员).SetValue(destObject,value);
其他的
抛出新异常(“属性必须为FieldInfo或PropertyInfo类型”);
}
公共静态类型GetMemberType(此MemberInfo成员){
开关(成员.成员类型){
案例成员类型。字段:
返回((FieldInfo)成员)。字段类型;
案例成员类型。属性:
返回((PropertyInfo)成员);
案例成员类型。事件:
return((EventInfo)成员).EventHandlerType;
违约:
抛出新ArgumentException(“如果类型为FieldInfo、PropertyInfo或EventInfo,则MemberInfo必须为”“member”);
}
}
您可以获取包含列的成员列表并分配它们:

public static IEnumerable<T> ToEnumerable<T>(this DataTable dt) where T : new() {
    var props = typeof(T).GetMembers(BindingFlags.Public|BindingFlags.Instance)
                         .Where(p => dt.Columns.Contains(p.Name) && (p.MemberType == MemberTypes.Field || p.MemberType == MemberTypes.Property)).ToList();
    foreach (var row in dt.AsEnumerable()) {
        var aT = new T();
        foreach (var p in props)
            p.SetValue(aT, row[p.Name]);
        yield return aT;
    }
}
公共静态IEnumerable到numerable(此数据表dt),其中T:new(){
var props=typeof(T).GetMembers(BindingFlags.Public | BindingFlags.Instance)
.Where(p=>dt.Columns.Contains(p.Name)和&(p.MemberType==MemberTypes.Field | | p.MemberType==MemberTypes.Property)).ToList();
foreach(dt.AsEnumerable()中的变量行){
var aT=新的T();
foreach(道具中的var p)
p、 设置值(在第行[p.Name]);
收益率;
}
}

我想这会有帮助。我相信你应该创建地图IDataReader,List。这可能对您有所帮助您可以为
Task
创建一个构造函数,该构造函数将
DataRow
作为其参数。您的代码有点冗余-没有理由创建一个
新列表
,然后立即丢弃它,只需使用
var tasks=
并去掉前一行即可。但是,对于包含更多字段的通用解决方案,您需要进行反射。您确定首先需要
DataTable
?为什么不更改数据层,使其返回一个
列表
?我正在返回一个列表。您是说我不需要使用ADO.NET从数据库检索数据吗?请怀疑这是否适用于var-除非您直接指定类型。@user6144226谢谢,因为它不在代码中,任务类型已被删除。