C# 类型为'的表达式;System.Int32';不能用于返回类型';System.Object';

C# 类型为'的表达式;System.Int32';不能用于返回类型';System.Object';,c#,.net,lambda,C#,.net,Lambda,我正在尝试生成一个简单的脚本系统,用于打印标签。我以前用反射做过这件事,没有问题,但现在我尝试用Lambda函数来做,这样我就可以缓存函数以供重用 到目前为止,我的代码如下 public static string GetValue<T>(T source, string propertyPath) { try { Func<T, Object> func; Type type = typeof(T); Par

我正在尝试生成一个简单的脚本系统,用于打印标签。我以前用反射做过这件事,没有问题,但现在我尝试用Lambda函数来做,这样我就可以缓存函数以供重用

到目前为止,我的代码如下

public static string GetValue<T>(T source, string propertyPath) {

    try {

        Func<T, Object> func;

        Type type = typeof(T);
        ParameterExpression parameterExpression = Expression.Parameter(type, @"source");
        Expression expression = parameterExpression;
        foreach (string property in propertyPath.Split('.')) {
            PropertyInfo propertyInfo = type.GetProperty(property);
            expression = Expression.Property(expression, propertyInfo);
            type = propertyInfo.PropertyType;
        }

        func = Expression.Lambda<Func<T, Object>>(expression, parameterExpression).Compile();

        object value = func.Invoke(source);
        if (value == null)
            return string.Empty;
        return value.ToString();

    }
    catch {

        return propertyPath;

    }

}
publicstaticstringgetvalue(T源,stringpropertypath){
试一试{
Func Func;
类型=类型(T);
ParameterExpression ParameterExpression=Expression.Parameter(类型@“源”);
表达式=参数表达式;
foreach(propertyPath.Split('.')中的字符串属性){
PropertyInfo PropertyInfo=type.GetProperty(属性);
expression=expression.Property(expression,propertyInfo);
类型=propertyInfo.PropertyType;
}
func=Expression.Lambda(表达式,参数Expression.Compile();
对象值=函数调用(源);
如果(值==null)
返回字符串。空;
返回值.ToString();
}
抓住{
返回属性路径;
}
}
这在某些情况下似乎有效,但在另一些情况下却失败了。问题似乎在于我试图将值作为对象返回,而与实际的数据类型无关。我尝试这样做是因为我不知道在编译时数据类型是什么,但从长远来看,我只需要一个字符串

每当我尝试访问Int32类型的属性时,我都会得到此消息标题中显示的异常,但对于可为null的类型和其他类型,我也会得到它。 当我试图将表达式编译到函数中时,会引发异常

有谁能建议我如何在维护Lambda功能的同时以不同的方式处理此问题,以便缓存访问器吗?

您是否尝试过使用?这将添加装箱/提升/etc转换

Expression conversion = Expression.Convert(expression, typeof(object));
func = Expression.Lambda<Func<T, Object>>(conversion, parameterExpression).Compile();
Expression conversion=Expression.conversion(Expression,typeof(object));
func=Expression.Lambda(转换,参数表达式).Compile();

我希望这段代码能对您有所帮助

使用系统;
使用System.Linq;
使用System.Linq.Expressions;
运用系统反思;
命名空间学生
{
班级计划
{
静态void Main(字符串[]参数)
{
var a=新学生();
PrintProperty(简称“名称”);
PrintProperty(a,“年龄”);
Console.ReadKey();
}
私有静态void PrintProperty(TA,字符串propName)
{
PrintProperty(a,propName);
}
私有静态void PrintProperty(TA,字符串propName)
{
ParameterExpression ep=表达式参数(类型为(T),“x”);
MemberExpression em=Expression.Property(ep,typeof(T).GetProperty(propName));
var el=Expression.Lambda(Expression.Convert(em,typeof(object)),ep);
Console.WriteLine(GetValue(a,el));
}
私有静态TPorperty GetValue(tV,表达式)
{
返回表达式.Compile().Invoke(v);
}
公立班学生
{
公立学生()
{
Name=“阿尔伯特·爱因斯坦”;
年龄=15岁;
}
公共字符串名称{get;set;}
公共整数{get;set;}
}
}
}

您与这个答案非常接近,只是需要转换的是“表达式”,而不是编译前的“参数表达式”(expression=expression.Convert(expression,typeof(Object));)。谢谢。非常感谢!:)@JonSkeet:你会如何为一个属性设置者做同样的事情?我已经尝试了我所能想到的每一个表达式操作来转换到另一个方向,但没有一个完全有效?@JoshuaFrank:我建议你用一个完整的例子来问一个新问题,说明你正在尝试做什么。大多数情况下,您可能希望使用一个属性链,其中除最后一个表达式外,其他所有表达式都是getter,而最后一部分是setter。但如果没有一个例子来尝试修正,就很难比这更具体。
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace Student
{
    class Program
    {
        static void Main(string[] args)
        {
            var a = new Student();
            PrintProperty(a, "Name");
            PrintProperty(a, "Age");
            Console.ReadKey();

        }
        private static void PrintProperty<T>(T a, string propName)
        {
            PrintProperty<T, object>(a, propName);
        }
        private static void PrintProperty<T, TProperty>(T a, string propName)
        {
            ParameterExpression ep = Expression.Parameter(typeof(T), "x");
            MemberExpression em = Expression.Property(ep, typeof(T).GetProperty(propName));
            var el = Expression.Lambda<Func<T, TProperty>>(Expression.Convert(em, typeof(object)), ep);
            Console.WriteLine(GetValue(a, el));
        }

        private static TPorperty GetValue<T, TPorperty>(T v, Expression<Func<T, TPorperty>> expression)
        {
            return expression.Compile().Invoke(v);
        }

        public class Student
        {
            public Student()
            {
                Name = "Albert Einstein";
                Age = 15;
            }
            public string Name { get; set; }
            public int Age { get; set; }
        }
    }
}