the object cloud be any class, and I don't want to use reflection. 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();
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
.
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
.
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
. The way to do this is using 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
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.