#c# #.net #reflection #system.reflection #reflection.emit
#c# #.net #отражение #system.reflection #reflection.emit
Вопрос:
я пытаюсь обдумать отражение.Эмит, я играю с ним, чтобы понять, как это работает.
я пытаюсь реализовать этот метод:
public static object GetTableKeyValue(object tableValue) => tableValue.GetType().GetProperties().First(property => property.GetCustomAttribute<KeyAttribute>() is not null).GetValue(tableValue);
Это то, что я делал до сих пор:
public static object GetTableKeyValueReflectionEmit(object val)
{
var getTableKeyValue = new DynamicMethod("GetTableKeyValueReflectionEmit", typeof(object), new Type[] { typeof(object) }, typeof(object).Module);
getTableKeyValue.DefineParameter(1, ParameterAttributes.In, "tableValue");
var il = getTableKeyValue.GetILGenerator(256);
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, typeof(object).GetMethod(nameof(object.GetType)), null);
il.EmitCall(OpCodes.Call, typeof(Type).GetMethod(nameof(Type.GetProperties), new Type[] { }), null);
Func<PropertyInfo, bool> predicate = property => (!property.GetCustomAttribute<KeyAttribute>().Equals(null));
// im stuck here
il.EmitCall(OpCodes.Call, typeof(Enumerable).GetMember(nameof(Enumerable.First)).OfType<MethodInfo>().First(method => method.GetParameters().Length == 1), new Type[] { typeof(Func<PropertyInfo, bool>) });
il.EmitCall(OpCodes.Call, typeof(PropertyInfo).GetMethod(nameof(PropertyInfo.GetValue), new Type[] { typeof(object) }), new Type[] { typeof(object) });
il.Emit(OpCodes.Ret);
var getTableKeyValueDelegate = (GetTableKeyValueDelegate)getTableKeyValue.CreateDelegate(typeof(GetTableKeyValueDelegate));
return getTableKeyValueDelegate(val);
}
я не могу понять, как определить предикат типа Func<PropertyInfo, bool> и передать его первому методу, и я не могу найти действительно хорошую информацию об отражении.Эмит, я думаю, это не так часто.
Помощь была бы признательна.
Комментарии:
1. Используя LINQPad, вы можете просмотреть IL для кода и посмотреть, что генерирует компилятор. Обычно, однако, я бы предложил использовать
Expression.Compile
вместоReflection.Emit
.2. Я уже написал это с помощью Expression . Скомпилируйте, просто пытаясь сделать то же самое с отражением. Испускать, чтобы увидеть различия.
3. Возможно
il.Emit(Opcodes.Ldftn, predicate.GetMethodInfo())
?
Ответ №1:
Кажется, это работает для меня:
public static object GetTableKeyValueReflectionEmit(object val) {
var getTableKeyValue = new DynamicMethod("GetTableKeyValueReflectionEmit", typeof(object), new Type[] { typeof(object) }, typeof(object).Module);
getTableKeyValue.DefineParameter(1, ParameterAttributes.In, "tableValue");
var il = getTableKeyValue.GetILGenerator(256);
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, typeof(object).GetMethod(nameof(object.GetType)), null);
il.EmitCall(OpCodes.Call, typeof(Type).GetMethod(nameof(Type.GetProperties), new Type[] { }), null);
Func<PropertyInfo, bool> predicate = property => (!property.GetCustomAttribute<KeyAttribute>().Equals(null));
il.Emit(OpCodes.Ldftn, predicate.GetMethodInfo());
var miFirstGeneric = typeof(Enumerable).GetMember(nameof(Enumerable.First)).OfType<MethodInfo>().First(method => method.GetParameters().Length == 1);
var miFirst = miFirstGeneric.MakeGenericMethod(typeof(PropertyInfo));
il.Emit(OpCodes.Call, miFirst);
il.Emit(OpCodes.Call, typeof(PropertyInfo).GetMethod(nameof(PropertyInfo.GetValue), new Type[] { typeof(object) }));
il.Emit(OpCodes.Ret);
var getTableKeyValueDelegate = (GetTableKeyValueDelegate)getTableKeyValue.CreateDelegate(typeof(GetTableKeyValueDelegate));
return getTableKeyValueDelegate(val);
}
Комментарии:
1. Я получаю это исключение, когда я запускаю ваш код: System. ExecutionEngineException: исключение типа ‘System. Было вызвано исключение ExecutionEngineException.’
2. @MeydanOzeri Работает для меня в LINQPad?
3. @MeydanOzeri я понимаю, что вы имеете в виду … что-то все еще не так с
Ldftn
.