Question

I'm doing a little code generation with DynamicMethod and I have a problem that would be handily solved by adding a little state, like a field. Unfortunately, I can't push this state into one of the method's parameters, so I basically need to close over a local like this little lambda:

var i = 0;
return new Func<int>(() => i++);

What's the simplest way to do this?

Was it helpful?

Solution

I believe you can't do that, at least not directly. DynamicMethod lets you create a single CLR method and nothing else. C# methods don't have that limitation, they are free to create closure types and fields in them and whatever else they need.

To achieve what you want, you could use TypeBuilder to dynamically build a full type with a method and a field.

But a simpler option would be to create the method with the state as a parameter and then use a closure (or, alternatively, a normal object) to capture the state. Something like:

Action<TData> CaptureState<TState, TData>(
    Action<TState, TData> originalAction, TState initialState)
{
    var state = initialState;
    return data => originalAction(state, data);
}

You would then use it like this:

Action<State, string> generated = …;
Action<string> captured = CaptureState(generated, new State());
captured("data1");
captured("data2");

If your method needs to change the value of the state (and not just modify some properties on it), then you would need to use ref parameter for the state, but the principle works the same (it would also mean you would need to use custom delegate type).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top