Thanks to Mackenzie Zastrow, there's now a NuGet Package. You can find it at[^]
Even if the following example looks like Basic code, it is actually C# code used to generate a dynamic method that will read a text file and write all non-empty lines to the console:
string fileName = null;
string line = null;
StreamReader streamReader = null;
var method =
new FluentMethodBuilder(typeof(void)).
AddParameter(() => fileName).
AddLocal(() => streamReader).
AddLocal(() => line).
Body.
Using(() => streamReader, () => new StreamReader(fileName)).
Loop().
Assign(() => line, () => streamReader.ReadLine()).
If(() => line == null).
Break().
EndIf().
If(() => line.Length > 0).
Do(() => Console.WriteLine(line)).
EndIf().
EndLoop().
EndUsing().
EndBody().
Compile<Action<string>>();
method(@"Test.txt");
I love dynamic code, and I am not talking about the dynamic keyword, which allows us to access existing objects in a dynamic manner, I am talking about code that is generated at run-time. This opens a lot of possibilities, in special to implement classes that have a hard to follow or big pattern, also opening the possibility to do Aspect Oriented Programming easily.
dynamic
I can say that I used the following solutions to generate dynamic code:
And to avoid to continue repeating myself I wrote some solutions to make it easier to generate a new type at run-time, be it by implementing an interface and calling a proxy object to process the call or by using the DelegatedTypeBuilder, which allows new methods to be created having their implementations given by a delegate.
Yet there were still many problems: The solution that implements an interface only redirects interface declared methods to the proxy object, forbidding users from creating new properties at run-time and also requiring a single method to be capable of dealing with any of the run-time generated methods, using parameters in an untyped manner. The DelegatedTypeBuilder required a delegate that was already capable of doing all the code, which can be fine for small patterns but it is extremely limited if new fields are required or even if the generated method can be written in different manners.
DelegatedTypeBuilder
Also, there are the natural limitations of the Microsoft solutions. LINQ expressions are only compiled as dynamic methods, not entire types. Reflection.Emit dynamic modules can't call private members of other libraries, not even the library that created it, which forced me to make many things public when they shouldn't be. So, considering all the limitations, none of the existing solutions is really helpful when I simply want to create a new dynamic method fast and without constraints or a new type that had to deal with 2 or more fields per property. So, in a moment of inspiration (or maybe delirium, as I was sick and with fever) I decided to create something new and easier to use.
And that something new is a fluent type and method builder.
I am not going to explain in details the inner workings of the library, but the main points are:
FluentMethodBuilder
If you are worried about performance, well, don't be. The generated code is pretty fast. As it compiles expressions directly in memory, it avoids losing time generating a text file, saving it to disk and then invoking a large compiler (which is what usually happens if you use CodeDOM or similar solutions). Then, if you are compiling an isolated method it will have a single virtual call to be invoked or, if you are compiling an entire type and accessing it through an interface you will have two virtual calls. Even this can be reduced to a single virtual call if you set the respectVisibility parameter of the AddMethod to true, but in such case the generated method will not be able to access internal or private members of its generator.
respectVisibility
AddMethod
There are three classes that are the heart of this library:
FluentTypeBuilder
FluentExpression
So, let's view each one of them:
If you want to create a method that is not bound to a specific type you should instantiate a FluentMethodBuilder directly. You simply need to give the return type of the resulting method to its constructor.
With such method builder you have the following possibilities:
To add a parameter you should declare it as a local variable in your code and set the default value to it. This is needed only to make it possible to access such parameter by all the different expressions that will be built by the fluent method calls and the default value is only a validation requirement as we can't let variables without a value when building expression (because the C# compiler will complain) and I opted to check for the default value only to make it clear that it is not receiving the value declared in your local variable.
Then, in the call to AddParameter() you should give an expression that will access such local variable. So, to declare a parameter named name of type string, you should do:
AddParameter()
name
string
string name = null;
method.AddParameter(() => name);
From that point on, you can make your dynamic method use that parameter by doing something like:
method.Body.Do(() => Console.WriteLine("The name is: " + name));
And when you compile the method it will be compiled as a method that receives a name parameter, of type string, and all accesses that used your local name will, in fact, use that parameter.
When we write our own code we can usually access the same member twice, execute the same get method twice or we can access it only once, putting it into a local variable, and then access the local variable many times.
Well, in a fluent method you can also add local variables. They work in the exact same manner as the parameters. You should declare a local variable in the builder method, setting it to its default value, only to make such variable accessible by all the expressions that will be used to build the method, then you call AddLocal() with an expression that directly access such variable and that's enough to make that variable acessible to your calls.
AddLocal()
This one was done simply to avoid bugs. When you do something like:
method.Body.Assign(() => variable, () => 5);
The generated expression will naturally have access to such "variable", but it will share such variable with all threads and all calls to the generated method. This is usually not what you want, so you will probably need to call AddLocal().
But what if you want to share such variable? That's how it naturally works, but in my initial tests I was many times forgetting to declare a variable as a variable. The code was working and the errors were only visible if I created other instances. So, to avoid errors, I decided to generate exceptions if you access a field (that's what a local variable used by an expression becomes) without telling how it should be used.
So, if you want it to be shared by the generator code and by all calls of the generated code, you should register such variable with the AddExternal() call. It has exactly the same syntax of the AddParameter() and AddLocal(), but it will only avoid exceptions, as such variable don't need to be compiled as something else.
AddExternal()
This is where the magic really happens and this is where this code most deviate from LINQ expressions, even if it uses a lot of them.
The truth is: The Body will become a BlockExpression from LINQ to be compiled. The big difference here is how we can build it. When using normal LINQ expressions we are forced to create the inner parts before the outer parts. In small cases that's not a big deal, but the more complex the expression becomes, the harder it gets to write it (and later to read it).
Body
BlockExpression
With the fluent API we have the Body and we can keep "adding" new actions do be done. If you already have an expression (or if you can directly write it in C#) it is enough to call the Do() method, which will incorporate such expression in the method body.
Do()
As a fluent API, you can do things like:
method.
Do(() => Console.WriteLine("Action1")).
Do(() => Console.WriteLine("Action2"));
Or you can do:
method.Do(() => Console.WriteLine("Action1"));
method.Do(() => Console.WriteLine("Action2"));
So, if you have some conditions before deciding what you will add to your method, you are free to do one thing at a time. You don't need to build the entire expression in a single step.
Also there are many different methods to make things easier or simply overcome the natural limits of the C# compiler expression generation. For example, the C# compiler does not allow us to do this:
method.Do(() => value = 5);
It understands such command but it says that assignment expressions are not supported (well, at least in C# 4, I don't know about version 5 or even about future versions).
So, to solve that problem there are other methods, like Assign(). With it you can do this:
Assign()
method.Assign(() => value, () => 5);
Note: We are using two expressions here, one to access the variable and one to get the value, yet those two expressions will become one AssignExpression and will be incorporated in a into a single block expression during the compile phase.
AssignExpression
And yet more interesting than the Assign() are the methods that create new blocks, like the If(), Try(), Loop(), While() and For().
If()
Try()
Loop()
While()
For()
Talking about the loop methods, that's something I consider bugged in LINQ expressions. I can't add a break or continue directly. I should give them the "target" to the beginning or to the end of the loop and, if I give the wrong target a break may end-up doing a continue and a continue may end-up doing a break. So, they are only doing gotos and shouldn't be different expressions. But I solved that problem, so you can call a Break() without any parameters and it will exit its enclosing loop.
break
continue
goto
Break()
To compile the method it is enough to call the Compile() method of the FluentMethodBuilder.
Compile()
If you don't give a delegate type to it, a default one will be chosen. If you give a delegate type, it must be compatible with the method. The validation part is, in fact, done by the LINQ expressions.
You can use the generic Compile<T>() method to avoid giving the type and also doing a cast to the same type on the obtained result if you know the delegate type at compile time.
Compile<T>()
The FluentTypeBuilder does not have a fluent API, yet each added method will use a FluentMethodBuilder and so, the most important part will be fluent.
When creating the FluentTypeBuilder you must give a generic parameter. That is the "base" type that will be used for the generated type. If you don't have any preference, it should be object.
object
In the constructor you can also pass all the interfaces that the type will implement.
Then, you can do the following:
And after you add all the code you need you can:
Type
GetConstructorDelegate()
In fact there is not much to explain about the FluentTypeBuilder, as the important part is the method generation (be it real methods or the properties that use get/set methods) and that's the job of the FluentMethodBuilder.
The FluentMethodBuilder has the Body property, where you can use a fluent API to add new statements. The problem is: When doing an If(), for example, it is possible that you don't have the entire expression that you should give as the If() parameter.
You may want to combine different And() and Or() conditions at run-time, but combining LINQ Expressions is not very easy (and in fact adding any condition using a Lambda expression instead of its inner Body usually generates strange bugs later instead of immediate exceptions).
And()
Or()
So, to avoid those problems you can use the FluentExpression.
With it, you can do things like:
var expression = FluentExpression.Create(() => firstCondition);
if (mustCheckSecondCondition)
expression.And(() => secondCondition);
if (useOrCondition)
expression.
Or(() => firstOrCondition).
Or(() => secondOrCondition);
You can very well do everything you want by combining expressions by hand, but I really consider this much easier to use.
I already gave a brief description of what a FluentMethodBuilder can do. Now, I want to present a brief list of the constructs you can use:
block.Do(() => Console.WriteLine("Test"));
block.Return(() => 5);
block.Assign(() => fieldOrVariable, () => value);
block.
If(() => x < 10).
Do(() => Console.WriteLine("x is less than 10.")).
Else().
Do(() => Console.WriteLine("x is at least 10.")).
EndIf();
block.
Using(() => variable, () => new DisposableObject()).
Do(() => Console.WriteLine("Here we can use the disposable object.")).
EndUsing();
block.
Loop().
Do(() => Console.WriteLine("This is an infinite loop.")).
EndLoop();
block.
While(() => Application.IsRunning).
Console.WriteLine("New messages will be written while the application is running.").
EndWhile();
block.
For(() => i, () => i<10, FluentExpression.Increment(() => i)).
Do(() => Console.WriteLine(i)).
EndFor();
i
block.
Loop().
Assign(() => line, () => streamReader.ReadLine()).
If(() => line == null).
Break().
EndIf().
If(() => line.Length == 0).
Continue().
EndIf().
Do(() => Console.WriteLine(line)).
EndLoop();
Note: I changed the code presented in the beginning of the article to use the Continue() method. You are of course free to write the code the way you feel more comfortable.
block.
Try().
Do(() => MethodThatMayThrowExceptions()).
Catch(() => ioException).
Do(() => Console.WriteLine("An IOException was thrown.")).
Catch(() => exception).
Do(() => Console.WriteLine("An exception was thrown and it was not an IOException.")).
Finally().
Do(() => Console.WriteLine("Finalizing independently if expections were thrown or not.")).
EndTry();
Note: This code considers that the variables exception and ioException exist and that they have, respectively, the types Exception and IOException.
exception
ioException
Exception
IOException
block.Do(() =>anotherFluentMethod.Call("argument 0", 57, ...));
Note: The Call() method exists on the typed FluentMethodBuilders (the FluentVoidMethodBuilder and the FluentMethodBuilder<T>) and allows you to call another method that lives on the same type that you are actually building, as it is not possible to directly reference a method that was not built yet. This method only exists so the expressions can be built and it will not work if invoked directly.
Call()
FluentVoidMethodBuilder
FluentMethodBuilder<T>
block.Inline(anotherFluentMethod);
Note: This method will incorporate the body of another FluentMethod inside this method. This is not a call to another method and it was done only to support passing an entire method in some situations where an expression is expected. It is recommended that in most cases you use the Call() method just presented.
Note: all block statements that I used in the samples refer to an enclosing block. The default one it the Body of the FluentMethodBuilder, but when you do a Loop(), for example, it generates another block, the same way the If, Try, Catch etc generate blocks. Also, at the end of each action it is always possible to replace the ; by a . so you can add a new statement.
The heart of this library is the FluentTypeBuilder. With it, it is real easy to create new types at run-time and add any methods, properties, events and fields you want.
Yet I should say that what I usually do is to implement interfaces at run-time with an specific pattern and so, to avoid doing always the same kind of code that look for all properties, events and methods that should be implemented, I decided to make that easier.
If your purpose is to implement an interface or abstract class at run-time, see the AbstractTypeImplementer class. You should inherit it to do the work and it has abstract methods that you should override that will be called to implement methods, events and properties, and they will use the right types on properties and events so you can build your expression easily.
AbstractTypeImplementer
For example, this is the entire code of the NotifyPropertyChangedImplementer:
NotifyPropertyChangedImplementer
using System;
using System.ComponentModel;
using System.Reflection;
using System.Linq.Expressions;
namespace Pfz.TypeBuilding.AbstractTypeImplementers
{
public sealed class NotifyPropertyChangedImplementer<TAbstract>:
AbstractTypeImplementer<TAbstract>
{
private readonly Expression<Func<PropertyChangedEventHandler>>
_eventHandlerFieldExpression;
public NotifyPropertyChangedImplementer():
base(typeof(INotifyPropertyChanged))
{
}
public NotifyPropertyChangedImplementer(
Expression<Func<PropertyChangedEventHandler>> eventHandlerFieldExpression):
base(typeof(INotifyPropertyChanged))
{
_eventHandlerFieldExpression = eventHandlerFieldExpression;
}
private NotifyPropertyChangedGenerator<TAbstract> _generator;
protected override FluentTypeBuilder<TAbstract> CreateTypeBuilder(Type[] additionalInterfaces)
{
var result = base.CreateTypeBuilder(additionalInterfaces);
_generator = new NotifyPropertyChangedGenerator<TAbstract>(result, _eventHandlerFieldExpression);
return result;
}
protected override void ImplementProperty<T>(
FluentTypeBuilder<TAbstract> typeBuilder, PropertyInfo property)
{
_generator.AddProperty<T>(property.Name);
}
protected override void ImplementEvent<T>(
FluentTypeBuilder<TAbstract> typeBuilder, EventInfo eventInfo)
{
if (eventInfo.EventHandlerType != typeof(PropertyChangedEventHandler))
throw new NotSupportedException();
}
protected override void ImplementMethod(
FluentTypeBuilder<TAbstract> typeBuilder, MethodInfo method)
{
throw new NotSupportedException();
}
protected override void ImplementIndexerUntyped(
FluentTypeBuilder<TAbstract> typeBuilder, PropertyInfo indexer)
{
throw new NotImplementedException();
}
}
}
This class is capable of implementing the abstract properties of classes (or interfaces) so they will follow the pattern that a get is a direct field access and a set should call the PropertyChanged event if the new value is different from the old value.
PropertyChanged
As you can see, it will throw NotSupportedExceptions if there is any abstract method or indexer or if there's an event that is not the PropertyChanged one. You can also notice that to add the property there is a call to _generator.AddProperty.
NotSupportedException
_generator.AddProperty
Such generator (the NotifyPropertyChangedGenerator generic class) has the only purpose of creating properties that follow the INotifyPropertyChanged pattern, but it has the following capabilities:
NotifyPropertyChangedGenerator
INotifyPropertyChanged
So, here are some basic examples of how it can be used.
// The following generator does not tells how to access the
// field that stores the PropertyChanged handler, so it is considered
// that such event does not exist and must be declared.
var generator = NotifyPropertyChangedGenerator.Create(typeBuilder);
// The next statement adds a property named Name, which have its
// own backing field and will only notify its own change.
generator.AddProperty<string>("Name");
// The previous line could be written as:
generator.AddProperty("Name", typeof(string));
// The next line is an example of a property that notifies that more
// than one property was changed:
generator.AddProperty<DateTime>("Birthdate", "Age");
// And again, it could be written as:
generator.AddProperty("Birthdate", typeof(DateTime), "Age");
// And the next one is the most complex case: The get and set
// will be given. In the set, there is a validation before
// actually accepting the value:
int positiveIntField = 0;
typeBuilder.AddField("positiveIntField", () => positiveIntField);
int value = 0;
var setAction = FluentMethodBuilder.CreateAction().
Body.
If(() => value < 0).
Throw(() => new ArgumentException("Value must be greater than 0.")).
EndIf().
Assign(() => positiveIntField, () => value).
EndBody();
generator.AddProperty("PositiveInt", () =>
positiveIntField, setAction, () => value, "Age");
At least in .NET 4, the dynamic keyword is not capable of acessing the types generated at run-time. At first I thought it was my error, as I was generating all methods as private methods, but even when they are public they aren't acessible. I consider this really bizarre, because reflection sees all the properties and methods, WPF is capable of binding on the properties of the run-time generated objects, I can access them through interfaces but the dynamic keyword simply fails to access them.
Even if this is bizarre, I don't see a big problem with this. If you read a property named X you know such property exists, so why not create an interface with such property and ask the run-time generated type to implement it? And, if you really want run-time access to the object (like the one done by DataGrid) it will work too. But I am commenting about this problem because the first thing I tried to do with a dynamically created object was access it through the dynamic keyword, and that failed.
X
DataGrid
I know that Microsoft created the Roslyn project to expose the C# and VB compilers as services. I've never really used it but I believe someone might think my project is doing the same.
I don't know if Roslyn has a fluent API to create dynamic methods but I believe my library is much smaller and focused than Roslyn. I am not trying to create an entire compiler or exposing components that can be used by a compiler, I am only creating a small library that allows dynamic types and methods to be created easily. If you are using Roslyn and it is working fine for you, I really don't think this library will be useful to you. But if you want something small that will do the job, then this library is probably what you need.
The downloadable solution has the library and a small sample. You can consider the sample more of a guide on how to do things than an application. If you want to run it and see something beautiful, well, you will get frustrated. But if you are interested in knowing how to use the library, it may give you some examples.
Different from other articles, the library in this article does not include any other of my personal libraries. It is simply a small library that you can use anywhere you want.
I am definitely not going to write a tutorial on how to write this library, but I will explain some details on how it was implemented.
In the beginning of the article I said that Expressions only compile single methods and that Reflection.Emit dynamic modules can't call private members declared on other libraries (not even the one that created it).
So, to solve the problem, I decided to combine both: I use expressions to compile single methods and then I use Reflection.Emit to create a dynamic module with all the methods I need, to simply redirect to the methods created by the expressions.
I thought that will be directly possible, but the module in which the Expression compiles its method is also not accessible to the dynamic module. Seeing that there is the CompileToMethod() method in the LambdaExpression I tried it, believing that maybe that will solve my problem. But there are two problems with that method:
But I found a solution: The method in the dynamic module can call the delegates generated by the expressions. So, at the first moment, I was compiling the expressions (each FluentMethodBuilder will generate a single expression and compile it), putting all the delegates into an array and the dynamic module was compiled with a code to access such array, get the right delegate and invoke it.
This worked fine for the first tests, but then the big problem came: How do I access the fields that I will add to my type?
Even if I call DefineField() before compiling the expression, the type is not yet compiled, and the Expressions can only call already compiled types. On the first moment, instead of trying to change the logic I was considering each field to be an access to a ConditionalWeakTable. That worked, but aside from the performance impact of doing that, I didn't like the fact that if I debugged the type, it simple didn't had any fields.
ConditionalWeakTable
But I was doing one thing wrong: I was compiling the expressions to be able to get their delegate types (so the dynamic module could call it). But the dynamic module only needs to know the delegate types, not the actual delegates.
Considering that the delegate type is defined by the expression parameters and return type, I decided to create a "pre compile". When generating the dynamic module I only generate an empty expression with all the parameters and the return type. With this I can get the delegate type, without trying to really compile the expression that will access fields that don't exist yet. With the delegate types I am able to compile the dynamic module.
Then I visit and replace the expressions that represent a field access with the access to the real field (after all, it is compiled now) and everything works.
So, that's how I build a type composed of many individually compiled methods that are well capable of accessing the same fields. It is important to know that even if the expression methods are "static" it is always possible to give the instance on which they will work as a parameter, which I surely do.
The fluent interface of the library was another problem on its own. I started with a "block" of code. It had only some methods (like Do()) with added the expression and returned this.
this
By returning this the type of the return was of the block itself (the FluentBlockBuilder).
FluentBlockBuilder
The problem came when I added the If() method, which is also a block. First, I wanted that by calling EndIf() it returned to the right block. Second, as it was a block I thought about inheriting from the FluentBlockBuilder, but as a call to Do() was already returning this cast as FluentBlockBuilder I was losing the Else() method.
EndIf()
Else()
Here I had many solutions to the problem:
Catch()
EndBlock()
EndTry()
Else()
T Do<T>(T instance)
int
instance
FluentIfBuilder
using
Loop
FluentBlockBuilder<TParentBuilder, FluentIfBuilder>
If
I am sure there are other things that may be of interest, but those are the most important ones in my opinion.
AddMethod()
This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0
IFunction
Func<Double, Double>
Sacha Barber wrote:wok
ExpressionExtensions.ToCSharpString()
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.