2

I am working on a tool to generate assemblies for WP7. I am doing this from the full framework. Since Reflection.Emit doesn't work with WP7 but either CCI or Mono.Cecil do I am wondering if there is a way to create new assemblies from scratch. I already know that I can modify existing assemblies, but being able to create one would be pretty useful. I guess a workaround would be to generate an empty assembly in visual studio and keep it as a template, but I think that there should be a better way.

cloudraven
  • 2,484
  • 1
  • 24
  • 49

2 Answers2

2

It's pretty easy to do with Mono.Cecil:

using Mono.Cecil;
using Mono.Cecil.Cil;

class Demo
{

    static void Main()
    {
        var winphoneAssemblies = @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\Profile\WindowsPhone";

        var assemblyResolver = new DefaultAssemblyResolver();
        assemblyResolver.AddSearchDirectory(winphoneAssemblies);

        var winphoneCorlib = assemblyResolver.Resolve("mscorlib");

        var module = ModuleDefinition.CreateModule("Test", new ModuleParameters
        {
            AssemblyResolver = assemblyResolver,
            Runtime = TargetRuntime.Net_2_0,
            Kind = ModuleKind.Dll,
        });

        // trick to force the module to pick the winphone corlib
        module.Import(winphoneCorlib.MainModule.GetType("System.Object"));

        var type = new TypeDefinition("Test", "Type", TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract, module.TypeSystem.Object);
        module.Types.Add(type);

        var method = new MethodDefinition("Identity", MethodAttributes.Public | MethodAttributes.Static, module.TypeSystem.Int32);
        method.Parameters.Add(new ParameterDefinition("i", ParameterAttributes.None, module.TypeSystem.Int32));

        type.Methods.Add(method);

        var il = method.Body.GetILProcessor();
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Ret);

        module.Write("Test.dll");
    }
}

A few things to note:

  • The need to create the module with an assembly resolver targeting the winphone assemblies.
  • A little trick to make sure the module picks up the proper winphone mscorlib (will be fixed in the next version of Cecil).
  • Silverlight assemblies have the metadata version of the .net 2.0 framework.
Jb Evain
  • 17,319
  • 2
  • 67
  • 67
  • I have a follow up question. It is related to what Richard mentioned below. I tried to load the Test assembly generated by this example and call the static method "Identity" of the type "Type", I immediately get an Application Unhandled Exception. Is it possible to overcome this problem? – cloudraven Jul 23 '11 at 02:43
  • @cloudraven: Again, this is not related. In that case the sample I pasted contained a typo and triggered the creation of an invalid assembly. Always use peverify to check that you emit proper code. I updated the sample to generate a perfectly valid assembly. – Jb Evain Jul 23 '11 at 06:14
  • I see. Thanks! I ran peverify in the previous version to understand the problem. An Assembly cannot have a name with an extension. Now it works fine – cloudraven Jul 25 '11 at 01:25
2

It's worth pointing out that while you may be able to generate dynamic assemblies from within the phone's runtime using alternate framework's, you're not goint to be able to load / execute them. Those APIs will throw an exception if executed by application code.

Richard Szalay
  • 83,269
  • 19
  • 178
  • 237
  • It's true... I can reference it but I cannot use it – cloudraven Jul 23 '11 at 02:40
  • @cloudraven, no, that's a different issue all together. The issue is that you can generate assemblies at runtime in your WP7 application, but that you have nothing to load the assembly. – Jb Evain Jul 23 '11 at 06:08