使用反射在C#中实现动态LINQ语句

19

如果我有一个类似的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);

任何帮助都将是非常棒的。谢谢。


抱歉,我无法理解您的问题或代码 :(. 您能重新描述一下问题吗? - gustavodidomenico
GetValue 中的 p 是什么? - Raphaël Althaus
一个打字错误,应该是 o。我会进行编辑。 - erosebe
这是哪种类型的LINQ?LINQ to Objects,LINQ to Entities还是LINQ to SQL? - MarcinJuraszek
尝试指定BindingFlags.Instance | BindingFlags.Public作为绑定标志。 - vc 74
2个回答

46

你应该使用表达式树而不是反射。这样可以提高性能,并且它可以同时用于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; }
}

这个很好用。只需要对代码进行微小的调整,它就能做到我想要的了。谢谢。 - erosebe
@MarcinJuraszek 这正是我在寻找的。谢谢。 - Debopam Chanda

1

您不能使用反射,但是可以使用动态Linq,如这里所述。如果您正在使用Entity Framework,则还应该能够使用实体SQL,它基本上是一个硬编码的SQL字符串。


也许他可以使用表达式重写lambda函数。但我不确定他需要什么。 - gustavodidomenico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接