المساعد الشخصي الرقمي

مشاهدة النسخة كاملة : Reflection Emit: dynamically created type leads to "Common ******** Runtime detected an invalid program" no matter what



C# Programming
02-18-2010, 02:31 AM
Hi everyone. I've been stuck in pretty much four lines of code for 3 hours now, which is making me feel pretty useless http://www.barakasoft.com/script/Forums/Images/smiley_sigh.gif. If anyone can offer any insight I may build them a statue or something, because this is driving me crazy and I don't see any way out of it.

Alright, here's the thing. There's this class called ObjectFactory which takes a System.Type and creates an extended type. Let's say you call the ObjectFactory with a type called MyType. Then ObjectFactory will create a type called EXT_MyType which is a subclass of MyType and:
> Adds a field of type LockObject named lockObject (very original)
> For each constructor of MyType, it creates a constructor of EXT_MyType with the same arguments. This constructor first calls to the corresponding MyType constructor, and then creates an instance of LockObject and stores it in lockObject.

Now, I'm trying to modify this (this isn't my code) to remove the parts concerning lockObject. (I want to make other changes with respect to MyType, but that's not relevant now). The problem is, whatever change I make results in an exception saying "Common ******** Runtime detected an invalid program."

For example, here's the part that modifies the constructors, which works fine (this is the original code):

// constructorInfo is the ConstructorInfo of the constructor in the superclass (MyType)
public void TransformConstructor(ConstructorInfo constructorInfo) {

ParameterInfo[] paramList = constructorInfo.GetParameters();
Type[] args = new Type[paramList.Length];
for (int i = 0; i < args.Length; i++) {
args[i] = paramList[i].ParameterType;
}

ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(
constructorInfo.Attributes, constructorInfo.CallingConvention, args);

ConstructorInfo lockObjectConstructor
= typeof(LockObject).GetConstructor(new Type[] {typeof(object)});

ILGenerator ilGenerator = constructorBuilder.GetILGenerator();

ilGenerator.Emit(OpCodes.Ldarg_0);
// Copies the arguments onto the stack, since the contructor we're going
// to call (of the superclass) takes the same arguments.
for (int i = 0; i < args.Length; i++) {
ilGenerator.Emit(OpCodes.Ldarg, i + 1);
}
// Calls the constructor of the superclass (MyType).
ilGenerator.Emit(OpCodes.Newobj, constructorInfo);
// Creates a LockObject and stores it in the field lockObject of EXT_MyType.
--> ilGenerator.Emit(OpCodes.Newobj, lockObjectConstructor);
--> ilGenerator.Emit(OpCodes.Stfld, lockObjectField);
// Returns.
ilGenerator.Emit(OpCodes.Ret);
}

So that's fine, but if I remove the two lines pointed by arrows (which create the lock and store it in lockObject) I get a "Common ******** Runtime detected an invalid program."
After a lot of messing around and a mighty headache I decided to try another very simple thing, just to see if Common ******** Runtime is messing with me: I simply repeated these two lines, like so:

...... (the rest of the code is the same)
// Calls the constructor of the superclass (MyType).
ilGenerator.Emit(OpCodes.Newobj, constructorInfo);
// Creates a LockObject and stores it in the field lockObject of EXT_MyType.
--> ilGenerator.Emit(OpCodes.Newobj, lockObjectConstructor);
--> ilGenerator.Emit(OpCodes.Stfld, lockObjectField);
==> ilGenerator.Emit(OpCodes.Newobj, lockObjectConstructor);
==> ilGenerator.Emit(OpCodes.Stfld, lockObjectField);
// Returns.
ilGenerator.Emit(OpCodes.Ret);
}

The lines pointed by double arrows have been added. As you can see, I'm simply creating another LockObject and writing it to lockObject (overwriting the one we just created). I don't see how this could be wrong, but I once again get the message "Common ******** Runtime detected an invalid program."

I have absolutely no idea what to do.
By the way, the line that throws the exception is:

public object Create(params object[] args) {
return Activator.CreateInstance(extendedType, args);
}
where extendedType is the type after all the modifications, and args is actually empty.

The offer to build a statue to whoever helps stands. http://www.barakasoft.com/script/Forums/Images/smiley_wink.gif