18

If I have a LINQ statement like

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

how can I replace "id" and "name" with passed in variables using reflection? I keep getting object reference not set to instance of an object errors when I try. My attempts are things like

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

Any help would be great. Thanks.

erosebe
  • 927
  • 3
  • 16
  • 31

2 Answers2

44

You should use Expression Trees instead of reflection. It will perform better, and you'll be able to use it with both LINQ to Objects and 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);

then, you can get Name property using reflection (you'll do it just once, so it's fine to do it using reflection.

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

Test class is defined as

public class Test
{
    public int Id { get; set; }
    public string Name { get; set; }
}
MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263
1

You can't use reflection, but you can use dynamic Linq as described here. If you are using Entity Framework for this, you should also be able to use Entity SQL, which is basically a hard-coded SQL string.

Brian Mains
  • 50,520
  • 35
  • 148
  • 257