Я хочу иметь возможность использовать рефлексию для получения члена класса, скажем, типа IList, и я хочу создать для него делегат, чтобы я меньше платил за рефлексию.Все это так, что в последнее время я могу вызвать делегата, передав свой экземпляр и новый список.C # дает мне недопустимые исключения приведения каждый раз, когда я пытаюсь это сделать.Я что-то упустил из-за дженериков?
Я попытался использовать поля интерфейса без обобщения, и они, кажется, работают просто отлично.Кажется, я сталкиваюсь с проблемой только при использовании дженериков.Я также попытался использовать Convert.ChangeType для преобразования своего ввода в желаемый тип, и я получаю ошибки о том, что List <> не реализует IConvertible.Если я смогу установить значение типа IList <> из конкретного List <> с помощью отражения, я буду счастлив:)
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 });
}
}
Ожидаемые результаты для меня, чтобы я смог кешировать "установщик" всвойство и поддержка, устанавливающие значение любого типа, включая обобщенные и интерфейсы.Мой текущий результат заключается в том, что установка значений любого типа ЗАПРЕЩАЕТСЯ при наличии обобщений ... поэтому я должен что-то делать неправильно.