【问题标题】:Use reflection to make dynamic LINQ statements in C#使用反射在 C# 中创建动态 LINQ 语句
【发布时间】:2014-05-22 18:50:53
【问题描述】:

如果我有类似的 LINQ 语句

x = Table.SingleOrDefault(o => o.id == 1).o.name;

如何使用反射将“id”和“name”替换为传入的变量?当我尝试时,我不断收到未将对象引用设置为对象实例的错误。我的尝试是这样的

x = (string)Table.SingleOrDefault(o => (int?)o.GetType().GetProperty(idString)
.GetValue(o, null) == 1).GetType().GetField(nameString).GetValue(x);

任何帮助都会很棒。谢谢。

【问题讨论】:

  • 抱歉,我无法理解您的问题,甚至您的代码 :(。您能重新制作问题正文吗?
  • GetValue 中的 p 是什么?
  • 一个错字。应该是o。将编辑。
  • 它是什么类型的 LINQ? LINQ to Objects、LINQ to Entities、LINQ to SQL?
  • 尝试将BindingFlags.Instance | BindingFlags.Public指定为绑定标志

标签: c# linq reflection


【解决方案1】:

您应该使用表达式树而不是反射。它的性能会更好,并且您可以将它与 LINQ to Objects 和 LINQ to SQL/Entities 一起使用。

var source = new List<Test> { new Test { Id = 1, Name = "FirsT" }, new Test { Id = 2, Name = "Second" } };
var idName = "Id";
var idValue = 1;

var param = Expression.Parameter(typeof(Test));
var condition =
    Expression.Lambda<Func<Test, bool>>(
        Expression.Equal(
            Expression.Property(param, idName),
            Expression.Constant(idValue, typeof(int))
        ),
        param
    ).Compile(); // for LINQ to SQl/Entities skip Compile() call

var item = source.SingleOrDefault(condition);

然后,您可以使用反射获取Name 属性(您只需执行一次,因此使用反射即可。

var nameName = "Name";
var name = item == null ? null : (string) typeof(Test).GetProperty(nameName).GetValue(item);

Test 类定义为

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

【讨论】:

  • 这很好用。只需对代码稍作调整,它就可以满足我的要求。谢谢。
  • @MarcinJuraszek 这正是我想要的。谢谢。
【解决方案2】:

您不能使用反射,但可以使用动态 Linq,如 here 所述。如果您为此使用实体框架,您还应该能够使用实体 SQL,它基本上是一个硬编码的 SQL 字符串。

【讨论】:

  • 也许他可以使用表达式重写 lambda。但我不确定他是否需要。
猜你喜欢
  • 2014-01-09
  • 2016-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-23
  • 1970-01-01
  • 2020-01-19
相关资源
最近更新 更多