![](/img/trans.png)
[英]How do I determine the generic type of an implemented interface using reflection?
[英]How do I set value of field that is a generic interface through reflection?
我希望能够使用反射来获得IList类型的类的成员,并且我想为其创建一个委托,以便为反射花更少的钱。 所有这些使我可以通过传入实例和新的List来调用委托。 每当我尝试这样做时,C#都会给我无效的强制转换异常。 我在泛型中缺少一些愚蠢的东西吗?
我尝试过使用没有泛型的接口字段,并且这些字段似乎工作正常。 我似乎只在使用泛型时遇到问题。 我还尝试使用Convert.ChangeType将我的输入转换为所需的类型,并且出现有关List <>的错误,该错误未实现IConvertible。 如果我可以使用反射从具体的List <>设置IList <>类型的值,我会很高兴的:)
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
public class MyObject
{
public IList<int> MyField;
}
public class ReflectionPerfTesting
{
public void Run()
{
var testObject = new MyObject();
var field = testObject.GetType().GetField("MyField", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
InvokeUsingReflection(field, testObject);
}
private void InvokeUsingReflection(FieldInfo fieldInfo, object testObject)
{
var fieldType = fieldInfo.FieldType;
var sourceType = fieldInfo.DeclaringType;
// ZAS: create value parameter
var valueParam = Expression.Parameter(fieldType);
// ZAS: create targetParameter
var sourceParam = Expression.Parameter(sourceType);
var field = Expression.Field(sourceParam, fieldInfo);
var returnExpression = (Expression)Expression.Assign(field, valueParam);
if (!fieldType.IsClass)
{
returnExpression = Expression.Convert(returnExpression, fieldType);
}
// ZAS: create generic delegate from definition
var delegateType = typeof(Action<,>);
var genericType = delegateType.MakeGenericType(sourceType, fieldType);
// ZAS: Create lambda for faster access to setter using reflection. This is meant to be cached!
var lambdaExpression = Expression.Lambda(genericType, returnExpression, sourceParam, valueParam);
var lambda = lambdaExpression.Compile();
var lambdaInvokeMethod = lambda.GetType().GetMethod("Invoke");
var list = new List<int>();
lambdaInvokeMethod.Invoke(testObject, new object[] { list });
}
}
对我来说,预期的结果是能够将“ setter”缓存到该属性,并支持设置任何类型的值,包括泛型和接口。 我当前的结果是,在有泛型的情况下,任何类型的设置值都可以工作,所以我必须做错了什么。
您的lambda通话有误。 您必须在传递目标以及参数的lambda对象上Invoke
方法。
如果解决此问题,则可获得所需结果:
testObject.Dump();
var list = new List<int>();
lambdaInvokeMethod.Invoke(lambda, new object[] { testObject, list });
testObject.Dump();
Dumping object(MyObject)
MyField : null
Dumping object(MyObject)
MyField : []
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.