What I find it useful for:
When you write a program that invokes methods through delegate's "Invoke" function, debugger does not break on place where that exception is thrown in invoked method, it breaks on "Invoke" function, with original exception wrapped as InnerException of TargetInvocationException.
Timwi's approach solves that problem (debugger break position is in the invoked method, and there is no exception wrapping)
What is changed:
- made some modifications so it can be compiled for .Net 2.0
- InvokeDirect renamed to Invoke
- added Invoke overload that invokes constructor by ConstructorInfo
- (details can be seen in source, search for "Quazistax" in comments)
- For each new constructor signature, dynamically create class with static method that returns object created using "new" on desired ConstructorInfo, and cache that method in dictionary with provided ConstructorInfo as key.
e.g. for Form parameterless constructor we dynamically create something like this:
Dynamically creating method that calls constructor with specified signature:
public class FormConstructorGeneratedClass { public static Form Construct() { return new Form(); } }
private static MethodInfo createConstructorMethod(ConstructorInfo con, string sig) { var typeBuilder = modBuilder.DefineType("construct " + sig + ".GeneratedClass", TypeAttributes.Public, typeof(object)); // Create a Construct method that creates new object trough given constructor var methodBuilder = typeBuilder.DefineMethod("Construct", MethodAttributes.Public | MethodAttributes.Static, con.DeclaringType, getParameterTypes(con)); // Now generate IL which will do constructing. // Generated IL is equivalent to the following single line of C# code: // return new ConstructedType(parameters[0], parameters[1], ...); // assuming that ConstructedType is type for which ConstructorInfo is given var il = methodBuilder.GetILGenerator(); ParameterInfo[] parameters = con.GetParameters(); for (int i = 0; i < parameters.Length; ++i) EmitLdarg(il, i); il.Emit(OpCodes.Newobj, con); //calling constructor il.Emit(OpCodes.Ret); return typeBuilder.CreateType().GetMethod("Construct"); }
- When invoking constructor, get from cache method created in step before and invoke it through Timwi's approach
You can get the source here.
No comments:
Post a Comment