Linq Expressions: Assign private fields (.NET 4)


Hold your horses, you might not see this untill 2010

In one of the PDC sessions I heard that the Linq.Expressions namespace have been extended so that it now contains expressions for pretty much everything that the new DLR can do.

Since my old post “Linq Expressions: Access private fields” is by far my most read blog entry, I figured that I have to throw you some more goodies.

So here it is, the code for assigning private fields using pure Linq Expressions:

public static Action<T, I> GetFieldAssigner<T, I>(string fieldName)
{

   ///change this to a recursive call that finds fields in base classes to..)
    var field = typeof(T).GetField (fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 

    ParameterExpression targetObject =
    Expression.Parameter(typeof(T), "target");

    ParameterExpression fieldValue =
    Expression.Parameter(typeof(I), "value");

    var assignment = Expression.AssignField(targetObject, field, fieldValue);

    LambdaExpression lambda =
    Expression.Lambda(typeof(Action<T, I>), assignment, targetObject, fieldValue);

    var compiled = (Action<T, I>)lambda.Compile();
    return compiled;
}

The code works pretty much the same way that my old field reader did except that this one will return an Action delegate that takes two args: target and fieldValue and returns void.

Some sample usage code:

Person roger = .....
var assigner = GetFieldAssigner<Person,string> ("firstName");
assigner(roger, "Roggan");

By using this approach you get a nice performance boost of about 300 times vs. using reflection with FieldInfo.SetValue.
(Assuming that you cache the assigner that is)

Pretty sweet.

BTW. Anyone know if this is available in the currently released DLR ?
In that case you won’t have to wait for .NET 4.

//Roger

CIL – Compiler construction


I’ve created a little sample on how to make your own .NET compiler.
The compiler uses Gold parser for parsing and Reflection.Emit to generate the compiled .exe file.

Initially I intended to make a sample on how to use Gold parser to parse and then compile Linq expressions, thus the name GoldLinq, however, Linq have now been replaced with Reflection.Emit.

Links:
My compiler source: http://www.puzzleframework.com/Roger/GoldLinq.zip
(C# VS.NET 2008 solution)

Gold parser: http://www.devincook.com/goldparser/
Grammar: http://www.devincook.com/goldparser/grammars/index.htm

How it works:

  • Gold parser – Calitha engine is used to parse the source code into a parse tree
  • The parse tree is transformed into a typed AST
  • The AST is verified using visitor pattern, the verifier handles type inferrence and auto casts.
  • The AST is optimized using visitor pattern, the optimizer replaces constant expressions and statements.
  • The AST is compiled into CIL/MSIL using visitor pattern.
  • If successful, the compiler will generate a file called “output.exe” in the same folder as the compiler

Samples:

Hello world 

display 'Hello World!'

 Have a nice day:

Display 'What is your name?' Read Name 
Display 'Hello, ' & Name & '. Have a nice day!'

Blastoff: 

assign n = 10 
while n >= 1 do 
    display n 
    assign n = n - 1 
end 
display 'Blast off!'

Miles and kilometers: 

Display 
'Do you want to convert 1) Miles to Kilometers or 2) Kilometers to Miles?' 
Read Choice        

if Choice == 1 then 
    Display 'Please enter the number of miles' Read Miles 
    Display Miles & ' Miles = ' & (Miles * 1.609)  & ' Kilometers' 
else 
    Display 'Please enter the number of kilometers' Read Kilometers 
    Display Kilometers & ' Kilometers = ' & (Kilometers / 1.609)  & ' Miles' 
end

Secret number: 

Assign SecretNumber = 64 

Display 'Please guess the secret number' 
Read Guess          

While Guess <> SecretNumber Do 
    If Guess < SecretNumber Then 
        Display 'Your guess was too LOW. Try again.' Read Guess 
    End     
If Guess > SecretNumber Then 
        Display 'Your guess was too HIGH. Try again.' Read Guess 
    End 
End     

Display 'Correct!'

How to compile the samples:

First you need a source file to compile, just create a normal textfile and paste one of the samples above into it.
Once you have the code file you can compile it using the compiler:

c:whatever\bin\debug> GoldSample.exe mysource.txt

When the compiler is done, you can start the compiled application with:

c:\whatever\bin\debug> output.exe

The code is somewhat too big to cover in a blog post, so if you have any questions feel free to ask in the comment section.

//Roger