Using CodeDOM.

Dynamic currying: part 2

Is said to in Europe, every man has an average of omega replica three watches, and to pay attention to the instrument famous Italy the average man watch has reached eight, these watches can mix and match clothing, to cope with a variety of uk replica watches occasions need. Here we are not talking about the fashion of men in Italy wear what table, but to explore the famous British Agent 007 James Bond in the film wearing what table. Isn't James Bond fashionable? The answer is obviously negative. Rolex Rolex, Omega and Seiko, is the most popular 007 favored brand, these brands period alternating from one side reflects the development path of rolex uk brand watches, and watch the performance in the film also a good interpretation of the brand connotation and the personality. ROLEX Rolex, OMEGA OMEGA and SEIKO precision, is the most popular brand of 007

When we left last time, we were just preparing to start using CodeDOM. So, let's put our sleeves up and do it:

CodeDOM has classes to represent parts of code we write, from compile unit (roughly the equivalent of Visual Studio project) down to statement, all in the System.CodeDom namespace.

We start simple, by declaring the compile unit, namespace and class:

var compileUnit = new CodeCompileUnit();

var curryingNamespace = new CodeNamespace("Currying");
compileUnit.Namespaces.Add(curryingNamespace);

var funcExtensionsClass = new CodeTypeDeclaration("FuncExtensions");
curryingNamespace.Types.Add(funcExtensionsClass);

This is where thighs start to get somewhat complicated, because now we want to add the method from the last part:

public static Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(Func<T1, T2, TResult> func)
{
    return p1 => p2 => func(p1, p2);
}

Because we'll be working with types like this a lot, I have written a bunch of functions to create them. They are in the source code repository, but I won't show their implementation here. This is the code to declare the function:

var curryMethod =
    new CodeMemberMethod
    {
        Attributes = MemberAttributes.Public | MemberAttributes.Static,
        ReturnType = CreateCurriedFuncType(1, i),
        Name = "Curry",
        Parameters =
            { new CodeParameterDeclarationExpression(CreateFuncType(i), funcParameterName) }
    };
curryMethod.TypeParameters.AddRange(CreateFuncTypeParameters(i).ToArray());

This does exactly what we do when we type the code by hand, except it's more verbose. We state that it's a public static method called Curry with return type, parameters and type parameters generated by helper methods. We have to specify TypeParameters separately, because it doesn't have public setter and it's not possible to use collection initializer with existing collection.

Now we want to write the method body. The problem is that CodeDOM tries to be language-agnostic and lambdas are feature of C#, not .Net. Fortunately, we can use so called snippets, which are strings containing any code, which can be language specific:

var parameters = Enumerable.Range(1, i).Select(j => "p" + j).ToArray();

string lambda = string.Format("{0} => {1}({2})", string.Join(" => ", parameters),
                                funcParameterName, string.Join(", ", parameters));

var lambdaExpression = new CodeSnippetExpression(lambda);

We can the use this expression in a return statement, and we are done with the method:

var returnStatement = new CodeMethodReturnStatement(lambdaExpression);

curryMethod.Statements.Add(returnStatement);

funcExtensionsClass.Members.Add(curryMethod);

We can now compile the assembly and we are done:

var provider = new CSharpCodeProvider();

provider.CompileAssemblyFromDom(
    new CompilerParameters(new[] { "System.Core.dll" }, "Currying.dll") { GenerateInMemory = false },
    compileUnit);

Or are we? Tune in next time to see, why we aren't done yet.

dotnet c# codedom
Posted by: Petr Onderka
Last revised: 03 Dec, 2016 07:36 PM History

Discussion

Matt Smith
Matt Smith
04 Jun, 2014 12:55 AM

Thanks. The lambda creation via CodeSnippet was just what I needed.

Your Comments

Used for your gravatar. Not required. Will not be public.
Posting code? Indent it by four spaces to make it look nice. Learn more about Markdown.

Preview