Finding a field of an object that matches a reference parameter in C #
When you write an iterator function in C # using the yield syntax, the compiler internally translates your function into a class. So if I write something like this:
IEnumerator<int> MyIterator () {
for (int i = 0; i < 10; i++)
yield return i;
}
Calling MyIterator () creates a class with a private field for i, instead of using a stack variable.
Now for the question: I want to find a way to find the field used to store the value of i. The reason has a little to do with this:
I am using iterator functions for collaborative streaming. I write simple code like this in an iterator to pause the execution of a function until the asynchronous operation completes.
Future<string> f;
yield return file.readLine(out f);
string line = f.Result;
When these three statements are executed, the readLine function is called and stores the future in field "f". The iterator function then pauses and falls back to backup when "f" of the Future has the result stored in it, after which I can get the result.
What I want to do is:
string line;
yield return file.readLine(out line);
Under normal circumstances, this is not possible in .NET as there is no guarantee that the stack variable will remain long enough for me to write it.
However, knowing that the iterator functions store all their locales inside fields, I can theoretically do this by holding the reference to the iterator (storing it) and the field itself, so that when the readLine operation completes, I can store the result directly into the field.
The problem is that the CLR doesn't seem to give me the ability to do this.
If I have an 'out' or 'ref' parameter, I can use unsafe C # or raw MSIL to convert that parameter to a raw pointer, reference, or TypedReference. Unfortunately, it is not legal to store any of these three types in a field - even if you trick the compiler into letting you do this, the bytecode verifier will not let you execute the code. This is most likely because keeping a reference to a stack variable would be inherently unsafe.
So what I want to do is write a function that takes an out / ref parameter and looks for the callsigns of the iterator fields to find the corresponding field. After it has this field, it stores the iterator and field reference to the wrapper type and associates the wrapper with the asynchronous operation.
Given the overhead associated with runtime reflection in .NET, I suspect this is not possible without preprocessing my source code or post-processing my assemblies after compilation.
However, I would love to hear some suggestions for alternative solutions. :) Any ideas?
a source to share
I finally found a solution that meets my needs and what you know is LINQ related.
The .NET blog mentioned how you can convert any lambda expression to an Expression <> object if you know the result type of the expression. With that in mind, it turns out that you can make an expression like this:
() => this.Foo.Bar
And go through the nodes so that you end up with a MemberInfo (for "Bar") and a 'this' object (for "this.Foo"). Given these two values, you can directly bind to a field or property specified at compile time. In the case of a property, you can do this very efficiently by extracting the Get and Set methods of the property from MemberInfo and converting them to strongly typed delegates, which makes the read / write cost of that property very low.
Best of all, it works great with automated refactoring and source code lookup because it puts the muscle of the compiler for you and it doesn't require any changes to existing code to allow binding.
The only drawback is that it is very difficult to bind to the fields / properties of the struct, but I still don't think this is a particularly important use case.
Anyone looking to solve this or a similar problem can look at the source code here:
http://code.google.com/p/fracture/source/browse/trunk/Squared/Util/Bind.cs
a source to share
Monkey with iterator fields asks forgiveness. Wouldn't it be easier to use the class member you specified in the iterator signature? Either a walkthrough or an exit? Basically with some sort of simple wrapper class?
class MyWrapper {
public string Line {get;set;}
}
allows you to talk to quietly Line
just by using an object reference MyWrapper
?
I didn't understand the whole question, so this is the best I can say ...
a source to share