C # Как вызвать первый метод LINQ с предикатом с использованием Reflection.Испускать

#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 .