Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / CLR / March 2008

Tip: Looking for answers? Try searching our database.

Using Reflection Emit and Creating Instances

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Joe McMenimen - 26 Mar 2008 17:06 GMT
I am trying to use the Reflection Emit capability of the framework to
dynamically inherit a base class. I want to call the base classes constructor
with arguments passed into the new classes constructor. I think I am close,
but get the following error trying to activate the new class.

System.Reflection.TargetInvocationException was unhandled
 Message="Exception has been thrown by the target of an invocation."
 Source="mscorlib"
 StackTrace:
      at System.RuntimeMethodHandle._InvokeConstructor(Object[] args,
SignatureStruct& signature, IntPtr declaringType)
      at System.RuntimeMethodHandle.InvokeConstructor(Object[] args,
SignatureStruct signature, RuntimeTypeHandle declaringType)
      at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags
invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
      at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr,
Binder binder, Object[] args, CultureInfo culture, Object[]
activationAttributes)
      at System.Activator.CreateInstance(Type type, BindingFlags
bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[]
activationAttributes)
      at System.Activator.CreateInstance(Type type, BindingFlags
bindingAttr, Binder binder, Object[] args, CultureInfo culture)
      at ReflectionEmit.Program.Main(String[] args) in C:\Documents and
Settings\jmcmeni\Desktop\ReflectionEmit\ReflectionEmit\Program.cs:line 47
      at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
      at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence
assemblySecurity, String[] args)
      at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
      at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
      at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
      at System.Threading.ThreadHelper.ThreadStart()
 InnerException: System.InvalidProgramException
      Message="Common Language Runtime detected an invalid program."
      Source="Test"
      StackTrace:
           at AmericanCar..ctor(String , String )
      InnerException:

Here is the small sample that I'm trying to get to work.

Any help would be great.

thanks

Joe

Program

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

namespace ReflectionEmit
{
   class Program
   {
       static void Main(string[] args)
       {
           AssemblyName assemblyName = new AssemblyName();
           assemblyName.Name = "Test";
           AssemblyBuilder assemblyBuilder =
Thread.GetDomain().DefineDynamicAssembly(assemblyName,
AssemblyBuilderAccess.RunAndSave);
           ModuleBuilder module;
           module = assemblyBuilder.DefineDynamicModule("Test.dll");

           // create a new type to hold our Main method
           TypeBuilder typeBuilder = module.DefineType("AmericanCar",
TypeAttributes.Public | TypeAttributes.Class, typeof(Car));

           typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
           FieldBuilder fb = typeBuilder.DefineField("brand",
typeof(string), FieldAttributes.Private);

           ConstructorInfo ci = typeof(Car).GetConstructor(new Type[] {
typeof(string) });

           ConstructorBuilder cb = typeBuilder.DefineConstructor(
ci.Attributes,
                        ci.CallingConvention, new Type[] { typeof(string),
typeof(string) });

           ILGenerator il = cb.GetILGenerator();
         
           int paramCount = ci.GetParameters().Length;
           il.Emit(OpCodes.Ldarg_0);
           for (int i = 1; i <= paramCount; i++)
           {
               il.Emit(OpCodes.Ldarg_S, i);
           }
           il.Emit(OpCodes.Call, ci);

           il.Emit(OpCodes.Ldarg_0);
           il.Emit(OpCodes.Ldarg_2);
           il.Emit(OpCodes.Stfld, fb);

           Type type = typeBuilder.CreateType();
           assemblyBuilder.Save("Test.dll");

           object o = Activator.CreateInstance(type,
BindingFlags.CreateInstance, null, new object[]{"Red","Corvette"},
System.Globalization.CultureInfo.CurrentCulture);

       }

   }

   public class Car
   {
       private string color;

       public string Color
       {
           get { return color; }
           set { color = value; }
       }

       public Car() { }

       public Car(string color)
       {
           this.color = color;
       }
   }
}
Joe McMenimen - 26 Mar 2008 18:38 GMT
Actually figurred out the issue. After creating the constructor and Emitting
the code to set the field, I forgot to Emit the return from the constructor.

il.Emit(OpCodes.Ret);

Joe

> I am trying to use the Reflection Emit capability of the framework to
> dynamically inherit a base class. I want to call the base classes constructor
[quoted text clipped - 124 lines]
>     }
> }
Ben Voigt [C++ MVP] - 26 Mar 2008 23:05 GMT
> Actually figurred out the issue. After creating the constructor and
> Emitting the code to set the field, I forgot to Emit the return from
> the constructor.
>
> il.Emit(OpCodes.Ret);

Best thing to do in these cases is to save the generated assembly (you
already do that, with SaveAndRun), and use Roeder's Reflector to look at the
IL.

Posting the IL is a lot better than the Reflection.Emit code that creates
it.... unless you know what IL you need and can't figure out what
Reflection.Emit calls would produce it.

In fact, sometimes Reflector will tell you what's wrong with the IL,
especially if you change the display language between IL and C#.
Joe McMenimen - 27 Mar 2008 20:04 GMT
Ben, that is exactly what I did. The suggestion of posting the IL is a great
idea.

Thanks again.

Joe

> > Actually figurred out the issue. After creating the constructor and
> > Emitting the code to set the field, I forgot to Emit the return from
[quoted text clipped - 12 lines]
> In fact, sometimes Reflector will tell you what's wrong with the IL,
> especially if you change the display language between IL and C#.
john conwell - 28 Mar 2008 16:25 GMT
I just ran across Reflector addin that might be really useful with writing
Reflection Emit code.

In the Reflector code window it shows the Reflection Emit code needed to
generate the method/class selected on the left panel in Reflector.

http://www.codeplex.com/reflectoraddins/Wiki/View.aspx?title=ReflectionEmitLangu
age&referringTitle=Home


I havent actually compared its generated Reflection Emit code to the code
i've written manually to validate its quality, but just playing around with
it, the generated code looks pretty good.

> Ben, that is exactly what I did. The suggestion of posting the IL is a great
> idea.
[quoted text clipped - 19 lines]
> > In fact, sometimes Reflector will tell you what's wrong with the IL,
> > especially if you change the display language between IL and C#.

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.