Какой самый простой способ добавить состояние в DynamicMethod CLR?
Я делаю небольшую генерацию кода с помощью DynamicMethod, и у меня есть проблема, которая может быть легко решена путем добавления небольшого состояния, например поля. К сожалению, я не могу вставить это состояние в один из параметров метода, поэтому мне нужно закрыть локальную область, например, такую маленькую лямбду:
var i = 0;
return new Func<int>(() => i++);
Какой самый простой способ сделать это?
1 ответ
Я считаю, что вы не можете сделать это, по крайней мере, не напрямую. DynamicMethod
позволяет вам создать один метод CLR и ничего больше. Методы C# не имеют такого ограничения, они могут создавать типы замыканий и поля в них и все, что им нужно.
Чтобы достичь того, что вы хотите, вы можете использовать TypeBuilder
динамически построить полный тип с помощью метода и поля.
Но более простой вариант - создать метод с состоянием в качестве параметра и затем использовать замыкание (или, альтернативно, обычный объект) для захвата состояния. Что-то вроде:
Action<TData> CaptureState<TState, TData>(
Action<TState, TData> originalAction, TState initialState)
{
var state = initialState;
return data => originalAction(state, data);
}
Вы бы тогда использовали это так:
Action<State, string> generated = …;
Action<string> captured = CaptureState(generated, new State());
captured("data1");
captured("data2");
Если вашему методу нужно изменить значение состояния (а не просто изменить некоторые свойства), вам необходимо использовать ref
параметр для состояния, но принцип работает так же (это также означает, что вам нужно будет использовать пользовательский тип делегата).