C# - Получить указатель на метод из сгенерированного метода из expression.Compile () - PullRequest
0 голосов
/ 17 апреля 2020

Я получаю указатель на метод со следующим:

public unsafe static long* GetPointer(MethodInfo info)
{
    // Simplified method without any checks    
    // if(IntPtr.Size == 4){ return (int*)info.MethodHandle.Value.ToPointer() + 2; }
    return (long*)info.MethodHandle.Value.ToPointer() + 1;
}


Func<string, int> func = x => 102;
var pointer = GetPointer(func.Method); // Works

Но если я хочу указатель сгенерированного метода из лямбда-выражения с помощью expression.Compile (), как в следующем фрагменте, я получаю следующая ошибка:

Запрошенная операция недопустима для DynamicMethod

Expression<Func<string, int>> expression = x => 102;
Func<string, int> func2 = expression.Compile();
var pointer = GetPointer(func2.Method); // Fails

Если я отлаживаю GetPointer, я получаю следующую информацию для MethodHandle - Атрибут:

MethodHandle = '((System.Reflection.Emit.DynamicMethod.RTDynamicMethod) info) .MethodHandle' сгенерировал исключение типа 'System.InvalidOperationException'

Кто-нибудь знает, как получить указатель сгенерированного метода? В конце я хочу заменить тело метода на тело другого метода. Метод замены тела взят из ответа SO здесь .

Обновление

Хорошо, я пытаюсь архивировать, например, переопределить результат DateTime.Now. В этом случае мой метод сначала пытается получить метод установки для свойства. Но DateTime.Now не имеет установщика, поэтому он пытается затем переопределить поле поддержки. Но DateTime.Now не имеет поля для переопределения, поэтому я хочу переопределить метод получения DateTime.Now. Мне нужно expression в первой попытке получить свойство / поле и получить экземпляр или тип, будь то свойство экземпляра или stati c. _methodCommands.SetGetter в настоящее время принимает два выражения Expression<Func<TResult>> expression, Expression<Func<TResult>> valueExpression. Теперь он ищет правильный метод получения и заменяет его методом из valueExpression (метод, принятый из этого ответа SO здесь ). Но здесь он не может получить указатель от любого из этих методов.

public class Commands
{
    private readonly IFieldCommands _fieldCommands;
    private readonly IPropertyCommands _propertyCommands;
    private readonly IMethodCommands _methodCommands;


    public Commands()
    {
        _fieldCommands = new FieldCommands();
        _propertyCommands = new PropertyCommands();
        _methodCommands = new MethodCommands();
    }


    public void SetProperty<TResult>(Expression<Func<TResult>> expression, TResult value)
    {
        if (expression == null) { throw new ArgumentNullException(nameof(expression)); }

        // Set value with the property setter method
        var state = _propertyCommands.Set<TResult>(expression, value);

        // Override value fom auto backed field of the property
        if (state == null) { state = _fieldCommands.SetBackingField(expression, value); }

        // Override getter of the property
        if (state == null) { state = _methodCommands.SetGetter<TResult>(expression, () => value); }

        if (state == null) { throw new NotImplementedException(); }
    }
}

// Example call
var commands = new Commands();
commands.SetProperty<DateTime>(() => DateTime.Now, new DateTime(2000,1,1));
var now = DateTime.Now; // Should equals new DateTime(2000,1,1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...