简体   繁体   English

C# 使用表达式从 object 获取值

[英]C# Use Expression to get value from an object

the object cloud be any class, and I don't want to use reflection. object 云是任何 class,我不想使用反射。 this is my code:这是我的代码:

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

        static void test()
        {
            object d = new Dog
            {
                Id = 21,
                Name = "adsf"
            };
            genericeTest(d);
        }

        static void genericeTest<T>(T t)
        {
            var type = t.GetType();
            var arg = Expression.Parameter(type, "x");
            var expr = Expression.Property(arg, "Id");
            var compiled = Expression.Lambda<Func<T, int>>(expr, arg).Compile();
            var value = compiled.Invoke(t);
        }

but there is exception System.ArgumentException: ParameterExpression of type 'ExpressionDemo.Program+Dog' cannot be used for delegate parameter of type 'System.Object' at var compiled = Expression.Lambda<Func<T, int>>(expr, arg).Compile();但有异常System.ArgumentException: ParameterExpression of type 'ExpressionDemo.Program+Dog' cannot be used for delegate parameter of type 'System.Object' var compiled = Expression.Lambda<Func<T, int>>(expr, arg).Compile();

if I write like this如果我这样写

   var compiled = Expression.Lambda<Func<Dog, int>>(expr, arg).Compile();
   var value = compiled.Invoke(t as Dog);

it works well.它运作良好。 can I fix it, thank you.我可以修一下吗,谢谢。

The problem is that your T is an object , because d has a compile-time type of object , but t.GetType() is Dog , because the runtime type of t is Dog .问题是您的Tobject ,因为d的编译时类型为object ,但t.GetType()Dog ,因为t的运行时类型是Dog

So you've got an expression which accepts a Dog , but you're trying to pass it a variable of type object -- you're missing the cast which would turn the object into a Dog .因此,您有一个接受Dog的表达式,但您试图将object类型的变量传递给它——您缺少将object变成Dog的演员表。

In other words, you're writing something roughly equivalent to:换句话说,您正在编写的内容大致相当于:

public int GeneratedMethod(object o)
{
    Dog d = o; // <-- This line will cause a compile-time error, of course
    return d.Id;
}

The question is, what do you want your generated method to look like?问题是,您希望生成的方法是什么样的? Should it look like this?它应该看起来像这样吗?

public int GeneratedMethod(object o)
{
    Dog d = (Dog)o;
    return d.Id;
}

If so, you'll need to insert the cast from object to Dog .如果是这样,您需要将演员表从object插入到Dog The way to do this is using Expression.Convert :这样做的方法是使用Expression.Convert

var type = t.GetType();
var arg = Expression.Parameter(typeof(T), "x");
var expr = Expression.Property(Expression.Convert(arg, type), "Id");
var compiled = Expression.Lambda<Func<T, int>>(expr, arg).Compile();

Here we're declaring a lambda which accepts a T , but then casts it to Dog .在这里,我们声明了一个 lambda ,它接受一个T ,然后将其转换为Dog

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM