LINQ : Dynamic select

前端 未结 10 736
北荒
北荒 2020-11-22 05:26

Consider we have this class :

    public  class Data
{
    public string Field1 { get; set; }
    public string Field2 { get; set; }
    public string Field         


        
10条回答
  •  北荒
    北荒 (楼主)
    2020-11-22 05:49

    The OP mentioned Dynamic Linq library, so I'd like to lay out an explanation on its usage.

    1. Dynamic Linq Built-In Select

    Dynamic Linq has a built-in Select method, which can be used as follows:

    var numbers = new List { 1, 2, 3 };
    var wrapped = numbers.Select(num => new { Value = num }).ToList();
    
    // the "it" keyword functions as the lambda parameter,
    // so essentialy it's like calling: numbers.Select(num => num)
    var selectedNumbers = numbers.Select("it"); 
    
    // the following is the equivalent of calling: wrapped.Select(num => num.Value)
    var selectedValues = wrapped.Select("Value");
    
    // the following is the equivalent of calling: numbers.Select(num => new { Value = num })
    var selectedObjects = numbers.Select("new(it as Value)"); 
    
    foreach (int num in selectedNumbers) Console.WriteLine(num);
    foreach (int val in selectedValues) Console.WriteLine(val);
    foreach (dynamic obj in selectedObjects) Console.WriteLine(obj.Value);
    

    The Downside

    There's somewhat a downside using the built-in Select:

    Since it's an IQueryable - not IQueryable - extension method, with IQueryable as its return type, common materialization methods - like ToList or FirstOrDefault - can't be used. This is why the above example uses foreach - it's simply the only convenient way of materializing the results.

    So to make things more convenient, let's support these methods.

    2. Supporting Select in Dynamic Linq (to enable using ToList and alike)

    To support Select, it needs to be added into the Dynamic Linq file. The simple steps for doing that are explained in this answer and in my comment on it.

    After doing so, it can be used in the following way:

    var numbers = new List { 1, 2, 3 };
    var wrapped = numbers.Select(num => new { Value = num }).ToList();
    
    // the following is the equivalent of calling: numbers.Select(num => num).ToList()
    var selectedNumbers = numbers.Select("it").ToList(); 
    
    // the following is the equivalent of calling: wrapped.Select(num => num.Value).ToList()
    var selectedValues = wrapped.Select("Value").ToList();
    
    // the following is the equivalent of calling: numbers.Select(num => new { Value = num }).ToList()
    var selectedObjects = numbers.Select("new(it as Value)").ToList(); 
    
    
    

    The Downside

    Arguably, this implementation introduces yet another kind of downside: By having to explicitly parameterize the Select call (e.g., having to call Select), we're losing the dynamic nature of the library.

    Nevertheless, since we can now call any materialization Linq method, this usage may still be quite useful.

    提交回复
    热议问题