views:

740

answers:

2

I need to generate a new interface at run-time with all the same members as an existing interface, except that I will be putting different attributes on some of the methods (some of the attribute parameters are not known until run-time). Can anyone assist?

+6  A: 

Your question isn't very specific. If you update it with more information, I'll flesh out this answer with additional detail.

Here's an overview of the manual steps involved.

  1. Create an assembly with DefineDynamicAssembly
  2. Create a module with DefineDynamicModule
  3. Create the type with DefineType. Be sure to pass TypeAttributes.Interface to make your type an interface.
  4. Iterate over the members in the original interface and build similar methods in the new interface, applying attributes as necessary.
  5. Call TypeBuilder.CreateType to finish building your interface.
Curt Hagenlocher
Nah, that's cool. I've not needed to use Reflection.Emit before so just wanted to see if anyone could spot a stumbling block in my evil master plan.
Matt Howells
+6  A: 

To dynamically create an assembly with an interface that has attributes:

using System.Reflection;
using System.Reflection.Emit;

// Need the output the assembly to a specific directory
string outputdir = "F:\\tmp\\";
string fname = "Hello.World.dll";

// Define the assembly name
AssemblyName bAssemblyName = new AssemblyName();
bAssemblyName.Name = "Hello.World";
bAssemblyName.Version = new system.Version(1,2,3,4);

// Define the new assembly and module
AssemblyBuilder bAssembly = System.AppDomain.CurrentDomain.DefineDynamicAssembly(bAssemblyName, AssemblyBuilderAccess.Save, outputdir);
ModuleBuilder bModule = bAssembly.DefineDynamicModule(fname, true);

TypeBuilder tInterface = bModule.DefineType("IFoo", TypeAttributes.Interface | TypeAttributes.Public);

ConstructorInfo con = typeof(FunAttribute).GetConstructor(new Type[] { typeof(string) });
CustomAttributeBuilder cab = new CustomAttributeBuilder(con, new object[] { "Hello" });
tInterface.SetCustomAttribute(cab);

Type tInt = tInterface.CreateType();

bAssembly.Save(fname);

That creates the following:

namespace Hello.World
{
   [Fun("Hello")]
   public interface IFoo
   {}
}

Adding methods use the MethodBuilder class by calling TypeBuilder.DefineMethod.

Colin Burnett