System.Reflection.AssemblyBuilder: adding referenced assemblys

  • Thread starter Thread starter Michael Sander
  • Start date Start date
M

Michael Sander

Hello ng,
anyone knowns how to add a reference to an assembly to
System.Reflection.AssemblyBuilder?

In System.Web.Compilation.AssemblyBuilder is a function like
AddAssemblyReference, but not in System.Reflection.

Regards,
Michael
 
oh, just found your answer. funny, my orginal entry has been deleted, but
your answer ist there.

yes, i need to i guess. the problem is, that i create an interface there,
that inherits from some other interface.

if both interfaces a created in the dynamic assembly all works fine.
if the base interface is created in some other assembly it wont show up in
the class viewer as base type of my dynamic interface.
even more weird: i can create an object of the type of the dynamic
interface, query the implemented interfaces an it shows the dynamic
interface. but the cast fails.
 
OK, here's a complete example that declares an interface in one
dynamic assembly, implements it in another, and then tests the
interface via reflection. It also saves both assemblies to disk so you
can load them in reflector/ildasm and verify that the references have
been set correctly (which they have, for me at least...):

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

namespace ConsoleApplication3
{
class Program
{
static void Main()
{
AssemblyBuilder assembly =
AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("Foo"),
AssemblyBuilderAccess.RunAndSave);
ModuleBuilder module =
assembly.DefineDynamicModule("Foo.dll");
TypeBuilder tb = module.DefineType("IFoo",
TypeAttributes.Interface | TypeAttributes.Abstract |
TypeAttributes.Public);
PropertyBuilder prop = tb.DefineProperty("Message",
PropertyAttributes.None, typeof(string), Type.EmptyTypes);
MethodBuilder method = tb.DefineMethod("get_Message",
MethodAttributes.Public | MethodAttributes.HideBySig
| MethodAttributes.NewSlot | MethodAttributes.Abstract
| MethodAttributes.Virtual, CallingConventions.HasThis,
typeof(string), Type.EmptyTypes);
prop.SetGetMethod(method);
Type ifoo = tb.CreateType();
assembly.Save("Foo.dll");


assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("Bar"),
AssemblyBuilderAccess.RunAndSave);
module = assembly.DefineDynamicModule("Bar.dll");
tb = module.DefineType("Bar", TypeAttributes.Class |
TypeAttributes.Sealed | TypeAttributes.Public);
tb.DefineDefaultConstructor(MethodAttributes.Public);
tb.AddInterfaceImplementation(ifoo);
MethodInfo interfaceMethod =
ifoo.GetMethod("get_Message");
method = tb.DefineMethod("MyMethodImpl",
MethodAttributes.Private | MethodAttributes.HideBySig
| MethodAttributes.NewSlot | MethodAttributes.Final |
MethodAttributes.Virtual | MethodAttributes.SpecialName
, CallingConventions.HasThis, typeof(string),
Type.EmptyTypes);
ILGenerator il = method.GetILGenerator();
il.Emit(OpCodes.Ldstr, "hello world");
il.Emit(OpCodes.Ret);
tb.DefineMethodOverride(method, interfaceMethod);
Type bar = tb.CreateType();
assembly.Save("Bar.dll");

typeof(Program).GetMethod("Test").MakeGenericMethod(ifoo,
bar).Invoke(null, null);
}

public static void Test<TInterface, TClass>()
where TInterface : class
where TClass : class, TInterface, new()
{
// create an instance
TClass obj = new TClass();

// check the cast (already validated by generic
constraint)
TInterface i = obj;

// try to read the property
PropertyInfo prop =
typeof(TInterface).GetProperty("Message");
object val = prop.GetValue(obj, null);
Console.WriteLine(val);
}
}
}
 
My main thoughts: are you calling AddInterfaceImplementation /
DefineMethodOverride? These are the important bits for applying the
interface implementation.

Also - sorry if the code (previous post) is ugly; it largely goes with
the turf for Reflection.Emit, I'm afraid...

Marc
 
hi marc,
i adjusted your example to meet my case. the cast works fine, there might be
some other issue in my code, but still i cant see IFoo/Foo as BaseType in
the ClassViewer.

using System;

using System.Reflection;

using System.Reflection.Emit;

namespace ConsoleApplication3

{

public interface IFoo

{

}

public class Foo : IFoo

{

}

class Program

{

static void Main()

{

AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new
AssemblyName("Bar"), AssemblyBuilderAccess.RunAndSave);

ModuleBuilder module = assembly.DefineDynamicModule("Bar.dll");

TypeBuilder tb = module.DefineType("IBar", TypeAttributes.Interface |
TypeAttributes.Abstract | TypeAttributes.Public);

tb.AddInterfaceImplementation(typeof(IFoo));

Type iBar = tb.CreateType();

tb = module.DefineType("Bar", TypeAttributes.Public | TypeAttributes.Class,
typeof(Foo));

tb.AddInterfaceImplementation(iBar);

Type bar = tb.CreateType();

assembly.Save("Bar.dll");

typeof(Program).GetMethod("Test").MakeGenericMethod(iBar, bar).Invoke(null,
null);

}

public static void Test<TInterface, TClass>() where TInterface : class where
TClass : class, TInterface, new()

{

TClass obj = new TClass();

TInterface i = obj;

}

}

}
 
I tried your code; it looks fine in reflector, so I imagine that VS is
just having a hard time resolving the interface back to the current
project assembly (or something).

As long as it works, I'd stop digging
[else it might stop working again!]

Marc
 
well, its only working in this tiny example. not in my app wich is far mor
complicated. i guess i will have to narrow this down.
thanks for your time and help!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top