C# 类型为'的表达式;System.Int32';不能用于返回类型';System.Object';
我正在尝试生成一个简单的脚本系统,用于打印标签。我以前用反射做过这件事,没有问题,但现在我尝试用Lambda函数来做,这样我就可以缓存函数以供重用 到目前为止,我的代码如下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
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; }
}
}
}