Wednesday, February 11, 2009

Extension Methods and CodeDom

A developer on my current project is creating a code generator and wondered how to emit extension methods. It turns out this is really easy.

All you have to do is emit a System.Runtime.CompilerServices.ExtensionAttribute on your static method and the class that contains it. Then just construct the method like a regular static method where the first parameter is the type you want to add the extension to. For example, to emit something like:

public static class StringExtensions {
public static string SayHi(this string instance)
{ ... }
}

you can emit:

[Extension]
public static class StringExtensions {
[Extension]
public static string SayHi(string instance)
{ ... }
}

Then make sure you reference System.Core.dll in your compiler options and everything will work fine.

4 comments:

Simon said...

How would you do this in VB, considering that VB only allows extension methods in Modules, not Classes?

Code Monkey said...

I don't know enough VB to help you here, sorry.

Anonymous said...

Correct me if I'm wrong, but I thought it was not possible to emit a static class with CodeDom.

Code Monkey said...

I have an old sample application for this that does this:

classDecl.Attributes = MemberAttributes.Public | MemberAttributes.Static;


where classDecl is a CodeTypeDeclaration.

Looking at the generated assembly in Reflector, the class doesn't actually end up static. I think what we can conclude from this is that a. you are right - you can't do static classes in CodeDom, but b. it doesn't matter - the extension methods having to be in a static class is only a C# compile-time limitation - if you reference the generated assembly and it has the right attributes (regardless of whether the class is static), the extension methods work as expected.