如何使用 LINQ return 在 C# 中选择所有属性或部分属性?

How to return either all properties or a selection of it in C# using LINQ?

我有一个接受 lambda 表达式的方法,该表达式指定 select 来自 table MyTable.

的列
public List<T> GetSelection<T>(string a, Expression<Func<MyTable, T>> columnsToSelect = null)
{
    IQueryable<MyTable> query = _myTableRepository.Where(c => c.Name == a);

    if (columnsToSelect != null)
        return query.Select(columnsToSelect).ToList();

    return query.ToList(); // Intellisense gives an error here, please read on
}

如您所见,columnsToSelect 的默认值为 null,允许我以以下两种方式之一调用此方法:

// passing in a lambda expression to select the columns I want
var result = GetSelection("AValue", t => new { t.Prop1, t.Prop2 }); 

// or like this, in which case I want all the columns
var result = GetSelection("AValue");

我从智能感知得到的错误是这样的:

Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List'

首先,我不理解这个令人困惑的错误消息,但我并不太在意。也就是说,我认为我需要的是一种将 MyTable 的整个对象转换为匿名类型然后 return 它的列表的方法,并通过 whole object 我的意思是匿名类型对象将包含 MyTable 的所有属性。我怎样才能做到这一点?

或者,如果有任何其他更好的方法来完成我想要的,请建议。

我认为你可以这样做:

if (columnsToSelect != null)
{
    var result = query.Select(s => s.GetType().GetProperty("columnName").GetValue(s, null).ToString())
                      .Select(s => new MyTable()
                      {
                          YourProperty = s.ToString()
                      }).ToList();
}

allowing me to call this method in any of the following two ways:

...

var result = GetSelection("AValue");

不,那是不允许的。编译器无法在此处推断出 T 的类型。解决这个问题的唯一方法是创建重载而不是使用默认值。此时问题变得微不足道:

public List<T> GetSelection<T>(
    string a, Expression<Func<MyTable, T>> columnsToSelect)
{
    return _myTableRepository.Where(c => c.Name == a).Select(columnsToSelect)
        .ToList();
}

public List<MyTable> GetSelection<MyTable>(string a)
{
    return GetSelection(a, t => t);
}

如果你能为你的table

定义一个接口
public interface IMyTable<T>
{
    string Name { get; set; }
    T GetAll();
}

然后这将编译

public List<T> GetSelection<T>(string a, Expression<Func<IMyTable<T>, T>> columnsToSelect = null)
{
    IQueryable<IMyTable<T>> query  = (IQueryable<IMyTable<T>>) _myTableRepository.Where(c => c.Name == a);

    if (columnsToSelect == null)
        columnsToSelect = (Expression<Func<IMyTable<T>, T>>)(table => (table.GetAll()));

    return query.Select(columnsToSelect).ToList();

}

用法演示

IMyTable<List<object>> xxx = new MyTable() { Surname = "b", Addresss = 1 };
xxx.Name = "a";
IMyTable<List<object>> yyy = new MyTable() { Surname = "d", Addresss = 2 };
yyy.Name = "c";
var repo = new List<IMyTable<List<object>>>() { xxx, yyy }.AsQueryable();
var Test = new Test<List<object>>(repo);
var generic = Test.GetSelection<List<object>>("c");
var specific = Test.GetSelection<List<object>>("c",
                (Expression<Func<IMyTable<List<object>>, List<object>>>) 
                    (x => new List<object>() { x.Name, ((MyTable)x).Addresss }));
var specifc2Columns = specific
    .Select(rows => new { Name = rows[0], Address = rows[1] });

演示 table 在哪里

 internal class MyTable : IMyTable<List<object>>
 {
     public string Surname { get; set; }
     public int Addresss { get; set; }
     string IMyTable<List<object>>.Name{ get; set; }
     List<object> IMyTable<List<object>>.GetAll()
     {
         return new List<object>() { ((IMyTable<List<object>>)this).Name, Surname, Addresss };
     }
 }