c# - 如何创建委托(delegate)来读取匿名类型的属性?

标签 c# reflection

我有一个使用匿名类型的实例调用的方法。类型始终相同,但实例不同。

注意:我只是将匿名对象作为对象类型传递。

我知道匿名类型有一个名为 Request 且类型为 HttpRequestMessage 的属性。这是我的方法,它是使用 info.Value 中的匿名类型执行的。

void IObserver<KeyValuePair<string, object> event> OnNext(KeyValuePair<string, object> info)
{
  HttpRequestMessage request = ?????
}

我可以像这样获取属性 getter:

MethodInfo propertyGetter = type.GetProperty("Request").GetGetMethod();

但是在读取传递给我的实例的属性时,我无法承受反射的成本。

如何创建一个委托(delegate),将实例传递给该委托(delegate)并获取属性值?

我试过了

private delegate HttpRequestMessage RequestPropertyGetterDelegate(object instance);
private static RequestPropertyGetterDelegate RequestPropertyGetter;

private static RequestPropertyGetterDelegate CreateRequestFromPropertyDelegate(Type type)
{
    MethodInfo propertyGetter = type.GetProperty("Request").GetGetMethod();
    return (RequestPropertyGetterDelegate)Delegate.CreateDelegate(typeof(RequestPropertyGetterDelegate), propertyGetter);
}

但是我遇到了绑定(bind)错误

System.ArgumentException: 'Cannot bind to the target method because its signature is not compatible with that of the delegate type.'

最佳答案

就是这样,使用表达式树。
您所要做的就是缓存getter,性能应该与直接访问相同。

void Main()
{
    var instance = new TestClass { Request = "Something 2" };
    var getter = CreateRequestFromPropertyDelegate(typeof(TestClass));
    // Cache getter per type
    var value = getter(instance);
    Console.WriteLine(value); // Prints "Something 2"
}

private delegate string RequestPropertyGetterDelegate(object instance);

static RequestPropertyGetterDelegate CreateRequestFromPropertyDelegate(Type type)
{
    // Entry of the delegate
    var instanceParam = Expression.Parameter(typeof(object), "instance");
    
    // Cast the instance from "object" to the correct type
    var instanceExpr = Expression.TypeAs(instanceParam, type);
    
    // Get the property's value
    var property = type.GetProperty("Request");
    var propertyExpr = Expression.Property(instanceExpr, property);
    
    // Create delegate
    var lambda = Expression.Lambda<RequestPropertyGetterDelegate>(propertyExpr, instanceParam);
    return lambda.Compile();
}

class TestClass
{
    // Using string here because I'm on LINQPad
    public string Request { get; set; }
}

关于c# - 如何创建委托(delegate)来读取匿名类型的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65551984/

相关文章:

java - 我可以声明返回 Class 对象的方法,但限制为 Java 中给定类型的子类吗?

c# - 动态代码生成

c# - 如何从Windows Phone访问MySQL?

c# - Autofac 中的装饰器和属性注入(inject)

c# - 以编程方式获取 Windows RunAsUser 提示

c# - 词典项目顺序

java - 哪个类调用了我的静态方法?

javascript - 返回带撇号的 JsonResult

c# - 如何通过反射获取 C# 属性名称作为字符串?

c# - 使用反射和 C# 调用静态方法时遇到问题