No code this week. I went on a hike instead.
Monthly Archives: July 2014
Formatting C# with Roslyn
2There’s already been a change to Roslyn that made my last bit of code obsolete. CustomWorkspace no longer requires a string in the constructor and is just:
new CustomWorkspace()
I found out how to change the formatting on the output. We can do this:
CustomWorkspace cw = new CustomWorkspace(); OptionSet options = cw.GetOptions(); options = options.WithChangedOption( CSharpFormattingOptions.OpenBracesInNewLineForMethods, false ); options = options.WithChangedOption( CSharpFormattingOptions.OpenBracesInNewLineForTypes, false ); SyntaxNode formattedNode = Formatter.Format( cu, cw, options );
With this change, our output code is now:
using System; using System.Generic; namespace MyNamespace { private partial class MyClass { } }
Generating Code with Roslyn
6Roslyn, now known as the .NET Compiler Platform, essentially provides a DOM for C# and Visual Basic. What it means for code generation is that you can construct an object representing your C# class and Roslyn will generate the .cs file.
This is the first in what I hope to be a series of posts showing how to generate particular elements. This will be for my own reference, if nothing else, but some may find it useful.
Preparing your Project
You’ll have to add the following references, probably using NuGet:
- Microsoft.CodeAnalysis
- Microsoft.CodeAnalysis.CSharp
- Microsoft.CodeAnalysis.CSharp.Workspaces
- Microsoft.CodeAnalysis.Workspaces
- Microsoft.CSharp
Just search NuGet for “CodeAnalysis” and you’ll find them.
Generating Classes from Scratch
The first thing I tried to do with Roslyn was to create an empty class from scratch but I couldn’t find any documentation online for how to do it. Every example I saw started by parsing an existing .cs file and making changes to it. So here’s how you do it.
Any file is considered a Compilation Unit. You can declare one like this:
CompilationUnitSyntax cu = SF.CompilationUnit()
And what’s the first thing in a .cs file? The “using”s. Add them like this:
CompilationUnitSyntax cu = SF.CompilationUnit() .AddUsings( SF.UsingDirective( SF.IdentifierName( "System" ) ) ) .AddUsings( SF.UsingDirective( SF.IdentifierName( "System.Generic" ) ) ) ;
The most important thing to note here is that all Roslyn objects are immutable. So saying:
cu.AddUsings( SF.UsingDirective( SF.IdentifierName( "System" ) ) )
Isn’t going to get you anywhere. AddUsings doesn’t change the cu object; It returns a new CompilationUnitSyntax with the change. You would have to write:
cu = cu.AddUsings( SF.UsingDirective( SF.IdentifierName( "System" ) ) )
So in Roslyn examples you’ll often see people chaining all their code together. I avoid it because it becomes unreadable and unmaintainable.
Next we’ll add a namespace:
NamespaceDeclarationSyntax ns = SF.NamespaceDeclaration( SF.IdentifierName( "MyNamespace" ) ); cu = cu.AddMembers( ns );
Now we’ll add our type to the namespace. We’ll declare it as a partial, private class.
ClassDeclarationSyntax c = SF.ClassDeclaration( "MyClass" ) .AddModifiers( SF.Token( SyntaxKind.PrivateKeyword ) ) .AddModifiers( SF.Token( SyntaxKind.PartialKeyword ) ) ; ns = ns.AddMembers( c );
Finally, we’ll write our type out to a file using the SyntaxTree type. This will write to any TextWriter (like StreamWriter). Here I write it out to a StringBuilder. Note that I have to specify a filename anyway (“C:\out.cs”, below). It doesn’t get used.
SyntaxNode formattedNode = Formatter.Format( cu, new CustomWorkspace( "Host" ) ); StringBuilder sb = new StringBuilder(); using ( StringWriter writer = new StringWriter( sb ) ) { formattedNode.WriteTo( writer ); }
And here’s what our class looks like:
using System; using System.Generic; namespace MyNamespace { private partial class MyClass { } }
Amazing.
I’ll have to figure out how to do something about the opening braces being on new lines. I don’t like putting opening braces on new lines.
[Edit 2015-08-23: See this update for some changes to Roslyn object names since this was first posted]
Test utilities
0I put some MSTest-based unit testing utilities up on github. So far I have FileAssert and DirectoryAssert classes that compare the contents of, as you would expect, files and directories. I do a lot of code generation and so it’s useful to be able to compare files and directories easily. I did some extra work so that when files and directories are different, the message that comes back is helpful and identifies the lines and character positions that differ. This is something you don’t get when simply comparing strings.
TFS Colorizer Stats
9As a developer, I can see some statistics about how my plugins are doing. The Chrome extension is actually doing pretty well. It’s getting about 11 downloads a week which is pretty good given that I haven’t really promoted it anywhere.
My Firefox add-in is still in review. When I submitted it to Mozilla almost two weeks ago I was asked if I wanted the 3-day preliminary review or the 10-day full review. I picked the quick 3-day review. you wouldn’t know it. I moved from 57th place yesterday to 54th today. Maybe they’re all watching the World Cup. Maybe they’re in the World Cup. Who knows.
Dynamically Generating Code at Run-Time with CIL
0I want to follow-up on yesterday’s post about the proxy generator with more details about how the code was created and what it does. First, I want to recap the problem I was trying to solve. With .NET web services and WCF, you use a client to connect to a server that implements an interface defining a service contract over a communications channel. As an example, let’s say your service contract does some simple math:
[ServiceContract] public interface IMathContract : IMathContractBase { [OperationContract] int Add( int a, int b ); [OperationContract] int Subtract( int a, int b ); [OperationContract] int Multiply( int a, int b ); [OperationContract] int Divide( int a, int b ); }
Pretty simple, right? The server’s implementation of the contract is pretty obvious:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] public class MathService : IMathContract { public int Add( int a, int b ) { return a + b; } public int Subtract( int a, int b ) { return a - b; } public int Multiply( int a, int b ) { return a * b; } public int Divide( int a, int b ) { if ( b == 0 ) throw new DivideByZeroException(); return a / b; } }
The only thing to note here is that if we call Divide with 0 as the denominator, we’re going to get a DivideByZeroException.
Our client is going to connect to the server via a communications channel. Assuming we’ve set up the server’s address and whatnot in the configuration file as “MathEndpoint”, the code to do some basic math looks like this:
ChannelFactory<IMathContract> factory = new ChannelFactory<IMathContract>( "MathEndpoint" ); IMathContract channel = factory.CreateChannel(); Console.WriteLine( "1 + 2 = " + channel.Add( 1, 2 ) ); Console.WriteLine( "4 - 1 = " + channel.Subtract( 4, 1 ) ); Console.WriteLine( "6 / 3 = " + channel.Divide( 6, 3 ) ); Console.WriteLine( "5 * 2 = " + channel.Multiply( 5, 2 ) );
Let’s say we’re worried about that DivideByZero exception so we guard against it.
ChannelFactory<IMathContract> factory = new ChannelFactory<IMathContract>( "MathEndpoint" ); IMathContract channel = factory.CreateChannel(); Console.WriteLine( "1 + 2 = " + channel.Add( 1, 2 ) ); Console.WriteLine( "4 - 1 = " + channel.Subtract( 4, 1 ) ); try { Console.WriteLine( "6 / 3 = " + channel.Divide( 6, 0 ) ); // DivideByZeroException } catch ( Exception ) { } Console.WriteLine( "5 * 2 = " + channel.Multiply( 5, 2 ) ); // CommunicationObjectFaultedException!
What happens? Well, even though we caught the exception, having any exception at all put our channel in the Faulted stage and so hen we call the next method, we get a CommunicationObjectFaultedException. Specifically, we get the message:
System.ServiceModel.CommunicationObjectFaultedException: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
If we want to keep using our service we have to abort the channel and create another. The fact is, an exception could happen at any time. Here it’s the result of bad input but it could be network timeouts or anything else. We don’t want to wrap every call to our service in a try…catch block capable of resetting our channel. Instead, we want to create a fault-tolerant wrapper or proxy around it.
Here’s a simplified proxy:
public class FaultSafeProxy : IMathContract { private readonly ChannelFactory<IMathContract> _factory; private IMathContract _channel; public FaultSafeProxy( string endpoint ) { this._factory = new ChannelFactory<IMathContract>( endpoint ); } #region Channel Management private void Abort() { if ( null == this._channel ) return; IServiceChannel serviceChannel = (IServiceChannel)this._channel; serviceChannel.Abort(); this._channel = null; } private void Close() { if ( null == this._channel ) return; IServiceChannel serviceChannel = (IServiceChannel)this._channel; serviceChannel.Close(); this._channel = null; } private IMathContract GetChannel() { if ( null == this._channel ) { this._channel = this._factory.CreateChannel(); } return this._channel; } #endregion #region IMathContract public int Add( int a, int b ) { try { return this.GetChannel().Add( a, b ); } catch ( Exception ) { this.Abort(); throw; } } // … #endregion }
Not bad, right? If we use our proxy we can call our methods safely:
FaultSafeProxy proxy = new FaultSafeProxy( "MathEndpoint" ); Console.WriteLine( "1 + 2 = " + proxy.Add( 1, 2 ) ); Console.WriteLine( "4 - 1 = " + proxy.Subtract( 4, 1 ) ); try { Console.WriteLine( "6 / 3 = " + proxy.Divide( 6, 0 ) ); // DivideByZeroException } catch ( Exception ) { } Console.WriteLine( "5 * 2 = " + proxy.Multiply( 5, 2 ) ); // Works!
So that all being said, our project might have dozens of interfaces and each interface has dozens of methods. How do we want to generate our proxies? We have a few options:
1. By Hand
We could hand-code a proxy for each interface in our project. This has a lot of drawbacks:
- It’s tedious
- Every time we add an interface we have to code another proxy
- Every time we add, remove, or change a method we have to change our proxy.
- If we ever wanted to change how our proxies worked (to add logging, say), we’d have to go through each class and update it by hand.
It’s pretty obvious that you don’t want to do this if you can avoid it.
2. Statically Generated Code
We could write an EXE that uses reflection to pull our service contracts out of our DLL and generate proxy classes for them. So that we don’t have to know the proxy types ahead of time we could also generate some sort of proxy factory that, given an interface type, could return the correct proxy type. This isn’t bad, but it has some drawbacks too:
- We would have to run this tool every time we added, removed, or changed a method or interface.
- Our project would have a lot of generated proxy classes that developers would have to know to ignore.
There’s still one better way, and the topic of this discussion:
3. Dynamically Generated Code
It would be best if we could just say “I want a proxy for IMyServiceContract” and have one handed back no matter what our service contract is. No extra classes. Nothing to maintain. Just a perfect proxy every time. That’s what we’re going to do here.
CIL
It’s pretty well known that .NET languages get compiled down to CIL, the Common Intermediate Language (formerly known as MSIL, or the Microsoft Intermediate Language). It’s less well known that you can actually generate CIL at run time creating whole assemblies in memory to be used just while your code is executing. So how do we do it? The first thing to do is to get an idea of the CIL that you want to generate. First we create a prototype of the class that we want to dynamically create. Our hand-coded proxy, above is a good example. When I compiled that code I got a DLL. Using the IL disassembler tool (which is part of the Microsoft Windows SDK and on my computer was found at C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\ildasm.exe) we can have a look.
You’re going to want to look at the CIL for the class, constructor, and all the methods in your prototype class. After that, you’re going to start building dynamic code.
Step 1: Create an assembly builder
// Create our dynamic assembly name and version AssemblyName assemblyName = new AssemblyName( ASSEMBLY_NAME ); assemblyName.Version = new Version( 1, 0, 0, 0 ); // Create the assembly builder, specifying whether we'll want to only run the assembly or run and save it AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly( assemblyName, // AssemblyBuilderAccess.Run AssemblyBuilderAccess.RunAndSave );
Note “Run” vs. “RunAndSave“. If you use “RunAndSave” your assembly will be created on disk, which is useful for debugging. In your final code, you’ll want to just use “Run“.
Step 2: Create a module builder
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule( assemblyBuilder.GetName().Name, assemblyBuilder.GetName().Name + ".mod" // Note: A module file name is necessary in order to save );
Step 3: Create a type builder
// Define our custom type, which implements the given interface and IDisposable TypeBuilder typeBuilder = moduleBuilder.DefineType( GenerateTypeName(), TypeAttributes.Class, typeof ( Object ), interfacesToImplement // type[] );
Here we specify our type name, the fact that it’s a class descended from Object, and the interfaces we want to implement.
Step 4: Add members
Now we just want to go through and add our members as we would to create the CIL we saw in the disassembler. Let’s look at our GetChannel method. In C#, it looks like this:
private IMathContract GetChannel() { if ( null == this._channel ) { this._channel = this._factory.CreateChannel(); } return this._channel; }]
In IL, it looks like this:
.method private hidebysig instance class TestProxyGenerator.Prototype.IMathContract GetChannel() cil managed { // Code size 47 (0x2f) .maxstack 2 .locals init ([0] class TestProxyGenerator.Prototype.IMathContract CS$1$0000, [1] bool CS$4$0001) IL_0000: nop IL_0001: ldnull IL_0002: ldarg.0 IL_0003: ldfld class TestProxyGenerator.Prototype.IMathContract TestProxyGenerator.Prototype.FaultSafeProxy::_channel IL_0008: ceq IL_000a: ldc.i4.0 IL_000b: ceq IL_000d: stloc.1 IL_000e: ldloc.1 IL_000f: brtrue.s IL_0024 IL_0011: nop IL_0012: ldarg.0 IL_0013: ldarg.0 IL_0014: ldfld class [System.ServiceModel]System.ServiceModel.ChannelFactory`1<class TestProxyGenerator.Prototype.IMathContract> TestProxyGenerator.Prototype.FaultSafeProxy::_factory IL_0019: callvirt instance !0 class [System.ServiceModel]System.ServiceModel.ChannelFactory`1<class TestProxyGenerator.Prototype.IMathContract>::CreateChannel() IL_001e: stfld class TestProxyGenerator.Prototype.IMathContract TestProxyGenerator.Prototype.FaultSafeProxy::_channel IL_0023: nop IL_0024: ldarg.0 IL_0025: ldfld class TestProxyGenerator.Prototype.IMathContract TestProxyGenerator.Prototype.FaultSafeProxy::_channel IL_002a: stloc.0 IL_002b: br.s IL_002d IL_002d: ldloc.0 IL_002e: ret } // end of method FaultSafeProxy::GetChannel
So how do we create that? Let’s go bit by bit. Start with a MethodBuilder and ILGenerator.
MethodBuilder methodBuilder = typeBuilder.DefineMethod( "GetChannel", MethodAttributes.Private | MethodAttributes.HideBySig, CallingConventions.Standard, typeof( T ), new Type[0] ); ILGenerator il = methodBuilder.GetILGenerator(); // Declare local variables il.DeclareLocal( typeof( T ) ); il.DeclareLocal( typeof( bool ) );
All the IL_00XX values are like GOTO labels and we can define them up front.
// Define some labels ahead of time Label label0024 = il.DefineLabel(); Label label002D = il.DefineLabel();
Use reflection to get some of the methods outside of our class, in this case ChannelFactory’s CreateChannel method.
// Get some methods ahead of time MethodInfo channelFactoryCreateChannelMethodInfo = typeof( ChannelFactory<T> ).GetMethod( "CreateChannel", new Type[0] );
Define our locals. This corresponds to
.locals init ([0] class TestProxyGenerator.Prototype.IMathContract CS$1$0000, [1] bool CS$4$0001)
il.DeclareLocal( typeof( T ) ); il.DeclareLocal( typeof( bool ) );
Then we emit the code that checks if our channel exists
IL_0000: nop IL_0001: ldnull IL_0002: ldarg.0 IL_0003: ldfld class TestProxyGenerator.Prototype.IMathContract TestProxyGenerator.Prototype.FaultSafeProxy::_channel IL_0008: ceq IL_000a: ldc.i4.0 IL_000b: ceq IL_000d: stloc.1 IL_000e: ldloc.1 IL_000f: brtrue.s IL_0024
il.Emit( OpCodes.Nop ); il.Emit( OpCodes.Ldnull ); il.Emit( OpCodes.Ldarg_0 ); il.Emit( OpCodes.Ldfld, this._channelField ); il.Emit( OpCodes.Ceq ); il.Emit( OpCodes.Ldc_I4_0 ); il.Emit( OpCodes.Ceq ); il.Emit( OpCodes.Stloc_1 ); il.Emit( OpCodes.Ldloc_1 ); il.Emit( OpCodes.Brtrue_S, label0024 );
If it doesn’t, we call the factory method to create it:
IL_0011: nop IL_0012: ldarg.0 IL_0013: ldarg.0 IL_0014: ldfld class [System.ServiceModel]System.ServiceModel.ChannelFactory`1<class TestProxyGenerator.Prototype.IMathContract> TestProxyGenerator.Prototype.FaultSafeProxy::_factory IL_0019: callvirt instance !0 class [System.ServiceModel]System.ServiceModel.ChannelFactory`1<class TestProxyGenerator.Prototype.IMathContract>::CreateChannel() IL_001e: stfld class TestProxyGenerator.Prototype.IMathContract TestProxyGenerator.Prototype.FaultSafeProxy::_channel IL_0024: ldarg.0 IL_0025: ldfld class TestProxyGenerator.Prototype.IMathContract TestProxyGenerator.Prototype.FaultSafeProxy::_channel IL_002a: stloc.0 IL_002b: br.s IL_002d
il.Emit( OpCodes.Nop ); il.Emit( OpCodes.Ldarg_0 ); il.Emit( OpCodes.Ldarg_0 ); il.Emit( OpCodes.Ldfld, this._factoryField ); il.Emit( OpCodes.Callvirt, channelFactoryCreateChannelMethodInfo ); il.Emit( OpCodes.Stfld, this._channelField ); il.Emit( OpCodes.Nop ); il.MarkLabel( label0024 ); il.Emit( OpCodes.Ldarg_0 ); il.Emit( OpCodes.Ldfld, this._channelField ); il.Emit( OpCodes.Stloc_0 ); il.Emit( OpCodes.Br_S, label002D );
And finally, we return the channel:
IL_002b: br.s IL_002d IL_002d: ldloc.0 IL_002e: ret
il.MarkLabel( label002D );il.Emit( OpCodes.Ldloc_0 );il.Emit( OpCodes.Ret );
I’m not going to lie. This can be a real pain in the ass to go through and debug. You’ll have to do this for each method you want to generate. Because you’re doing this dynamically, you’ll find yourself using reflection to iterate through the methods that you want to create.If you want to save your assembly to debug your type, this is the time to do it:
assemblyBuilder.Save( assemblyBuilder.GetName().Name + ".dll" );
Step 5: Create the Type and Object
Once you’re done with the TypeBuilder, you’re going to want to create an instance of your new type and that’s easy enough to do:
Type generatedType = typeBuilder.CreateType(); object instance = Activator.CreateInstance( generatedType, endpoint, userName, password );
And that’s it. You’ve got a dynamically generated type. If you made your type implement an interface, like a service contract in our example, you can just cast it to the interface and use the methods on it.
Fault-safe WCF Proxy Generator
0In WCF, clients connect to servers using channels that implement a particular service contract interface. This ordinarily works very well – until something throws an exception. Let’s say you’re a client, you have some channel object you can cast as IWhatever and you can make calls on its methods.
this._factory = new ChannelFactory<IMathContract>( endpoint ); this._channel = this._factory.CreateChannel(); int c = this._channel.Add( a, b );
If one of those methods throws an error, the channel will become faulted and every subsequent call will throw an exception like “The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.”. What you have to do now is abort and recreate the channel. But this error could happen anywhere. So what we usually do is build a proxy. The proxy wraps the channel, implementing all the interface’s methods, and aborts the channel if any of these calls throw an exception.
public int Add( int a, int b ) { try { return this.GetChannel().Add( a, b ); } catch ( Exception ) { this.Abort(); throw; } }
Writing these proxies is tedious, so I’ve created a utility that uses IL generation to dynamically generate a proxy given a service contract.
IMathContract channel = FaultSafeProxyEmitter<IMathContract>.Create( "MockEndpoint" );
This creates a fault-tolerant channel that will abort and reset if an exception is thrown. The channel will never remain in the Faulted state. The channel also implements IDisposable to properly close the underlying channel when complete.
The code is up on github.