Я получаю указатель на метод со следующим:
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)