[Mono-bugs] [Bug 29069][Maj] New - Delegate types created at runtime can't be used

bugzilla-daemon@rocky.ximian.com bugzilla-daemon@rocky.ximian.com
16 Aug 2002 20:41:41 -0000


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by nick@chemlab.org.

http://bugzilla.ximian.com/show_bug.cgi?id=29069

--- shadow/29069	Fri Aug 16 16:41:41 2002
+++ shadow/29069.tmp.20839	Fri Aug 16 16:41:41 2002
@@ -0,0 +1,325 @@
+Bug#: 29069
+Product: Mono/Runtime
+Version: unspecified
+OS: 
+OS Details: GNU/Linux
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Major
+Component: misc
+AssignedTo: mono-bugs@ximian.com                            
+ReportedBy: nick@chemlab.org               
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: Delegate types created at runtime can't be used
+
+Description of Problem:
+
+Delegate types created at runtime with System.Reflection.Emit.TypeBuilder
+can't be instantiated with System.Activator.
+
+This is also related to the class library bug #29036,
+"System.RuntimeMethodHandle not implemented". See Main() below for details.
+
+Steps to reproduce the problem:
+
+1. Compile and run the following code (sorry for the length).
+
+-- START --
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Collections;
+
+public class DelegateBuilder {
+	private static ParameterList ctorParams;
+
+	private AssemblyName assemblyName;
+	private Type returnType;
+	private string delegateName;
+	private ParameterList parameters;
+
+	private TypeBuilder tBuilder;
+
+	private Assembly assemblyResult;
+	private Type typeResult;
+
+	public string DelegateAssemblyName {
+		get { return assemblyName.Name; }
+		set { assemblyName.Name = value; }
+	}
+
+	public Type ReturnType {
+		get { return returnType; }
+		set { returnType = value; }
+	}
+
+	public string DelegateName {
+		get { return delegateName; }
+		set { delegateName = value; }
+	}
+
+	public ParameterList Parameters {
+		get { return parameters; }
+	}
+
+	public Assembly AssemblyResult {
+		get { return assemblyResult; }
+	}
+
+	public Type TypeResult {
+		get { return typeResult; }
+	}
+
+	static DelegateBuilder() {
+		ctorParams = new ParameterList();
+		ctorParams.Add(new Parameter("object", typeof(Object),
+ParameterAttributes.None));
+		ctorParams.Add(new Parameter("method", typeof(IntPtr),
+ParameterAttributes.None));
+	}
+
+	public DelegateBuilder() {
+		assemblyName = new AssemblyName();
+		DelegateAssemblyName = "NoAssemblyNameDefined";
+		ReturnType = typeof(void);
+		DelegateName = "NoDelegateNameDefined";
+		parameters = new ParameterList();
+	}
+
+	public void Build() {
+		TypeAttributes tAttr = TypeAttributes.Public | TypeAttributes.Class |
+TypeAttributes.Sealed;
+		AssemblyBuilder aBuilder =
+(AppDomain.CurrentDomain).DefineDynamicAssembly(assemblyName,
+AssemblyBuilderAccess.RunAndSave);
+		ModuleBuilder mBuilder = aBuilder.DefineDynamicModule(assemblyName.Name +
+".dll");
+		tBuilder = mBuilder.DefineType(delegateName, tAttr, typeof(MulticastDelegate));
+
+		BuildCtor();
+		BuildInvoke();
+		BuildBeginInvoke();
+		BuildEndInvoke();
+
+		typeResult = tBuilder.CreateType();
+		assemblyResult = aBuilder;
+	}
+
+	private void BuildCtor() {
+		MethodAttributes mattr = MethodAttributes.RTSpecialName |
+MethodAttributes.SpecialName |
+			MethodAttributes.HideBySig | MethodAttributes.Public;
+		ConstructorBuilder cBuilder = tBuilder.DefineConstructor(mattr,
+CallingConventions.Standard, ctorParams.ParamTypes);
+		cBuilder.SetImplementationFlags(MethodImplAttributes.Runtime);
+
+		for (int i=0; i<ctorParams.Count; i++) {
+			cBuilder.DefineParameter(i+1, ctorParams[i].ParamAttributes,
+ctorParams[i].ParamName);
+		}
+	}
+
+	private void BuildInvoke() {
+		MethodAttributes mAttr = MethodAttributes.Public | MethodAttributes.HideBySig
+| MethodAttributes.Virtual;
+		CallingConventions cConv = CallingConventions.Standard;
+		MethodBuilder mBuilder = tBuilder.DefineMethod("Invoke", mAttr, cConv,
+returnType, parameters.ParamTypes);
+		mBuilder.SetImplementationFlags(MethodImplAttributes.Runtime);
+
+		for (int i=0; i<parameters.Count; i++) {
+			mBuilder.DefineParameter(i+1, parameters[i].ParamAttributes,
+parameters[i].ParamName);
+		}
+	}
+
+	private void BuildBeginInvoke() {
+		MethodAttributes mAttr = MethodAttributes.Public | MethodAttributes.HideBySig |
+			MethodAttributes.Virtual | MethodAttributes.NewSlot;
+		CallingConventions cConv = CallingConventions.Standard;
+		ParameterList pList = parameters.Clone();
+		pList.Add(new Parameter("callback", typeof(AsyncCallback),
+ParameterAttributes.None));
+		pList.Add(new Parameter("object", typeof(Object), ParameterAttributes.None));
+		MethodBuilder mBuilder = tBuilder.DefineMethod("BeginInvoke", mAttr, cConv,
+typeof(IAsyncResult), pList.ParamTypes);
+		mBuilder.SetImplementationFlags(MethodImplAttributes.Runtime);
+
+		for (int i=0; i<pList.Count; i++) {
+			mBuilder.DefineParameter(i+1, pList[i].ParamAttributes, pList[i].ParamName);
+		}
+	}
+
+	private void BuildEndInvoke() {
+		MethodAttributes mAttr = MethodAttributes.Public | MethodAttributes.HideBySig |
+			MethodAttributes.Virtual | MethodAttributes.NewSlot;
+		CallingConventions cConv = CallingConventions.Standard;
+		ParameterList pList = new ParameterList();
+		pList.Add(new Parameter("result", typeof(IAsyncResult),
+ParameterAttributes.None));
+		MethodBuilder mBuilder = tBuilder.DefineMethod("EndInvoke", mAttr, cConv,
+typeof(void), pList.ParamTypes);
+		mBuilder.SetImplementationFlags(MethodImplAttributes.Runtime);
+
+		for (int i=0; i<pList.Count; i++) {
+			mBuilder.DefineParameter(i+1, pList[i].ParamAttributes, pList[i].ParamName);
+		}
+	}
+}
+
+public class Parameter {
+	private string pName;
+	private Type pType;
+	private ParameterAttributes pAttr;
+
+	public string ParamName {
+		get { return pName; }
+		set { pName = value; }
+	}
+
+	public Type ParamType {
+		get { return pType; }
+		set { pType = value; }
+	}
+
+	public ParameterAttributes ParamAttributes {
+		get { return pAttr; }
+		set { pAttr = value; }
+	}
+
+	public Parameter(string name, Type type, ParameterAttributes attrib) {
+		pName = name;
+		pType = type;
+		pAttr = attrib;
+	}
+}
+
+public class ParameterList {
+	private ArrayList parameterList;
+
+	public String[] ParamNames {
+		get {
+			String[] names = new String[parameterList.Count];
+			for (int i=0; i<names.Length; i++) {
+				names[i] = ((Parameter)parameterList[i]).ParamName;
+			}
+
+			return names;
+		}
+	}
+
+	public Type[] ParamTypes {
+		get {
+			Type[] types = new Type[parameterList.Count];
+			for (int i=0; i<types.Length; i++) {
+				types[i] = ((Parameter)parameterList[i]).ParamType;
+			}
+
+			return types;
+		}
+	}
+
+	public ParameterAttributes[] ParamAttributes {
+		get {
+			ParameterAttributes[] attribs = new ParameterAttributes[parameterList.Count];
+			for (int i=0; i<attribs.Length; i++) {
+				attribs[i] = ((Parameter)parameterList[i]).ParamAttributes;
+			}
+
+			return attribs;
+		}
+	}
+
+	public int Count {
+		get { return parameterList.Count; }
+	}
+
+	public ParameterList() {
+		parameterList = new ArrayList();
+	}
+
+	protected ParameterList(ArrayList newParameterList) {
+		parameterList = newParameterList;
+	}
+
+	public void Add(Parameter param) {
+		parameterList.Add(param);
+	}
+
+	public void RemoveAt(int idx) {
+		parameterList.RemoveAt(idx);
+	}
+
+	public void Remove(Parameter param) {
+		parameterList.Remove(param);
+	}
+
+	public Parameter this[int idx] {
+		get {
+			return (Parameter)parameterList[idx];
+		}
+	}
+
+	public ParameterList Clone() {
+		return new ParameterList((ArrayList)parameterList.Clone());
+	}
+}
+
+public class MainClass {
+	public void Foobar() {
+		Console.WriteLine("Foobar!");
+	}
+
+	public static void Main() {
+		DelegateBuilder db = new DelegateBuilder();
+		db.Build();
+		Type delType = db.TypeResult;
+
+		MainClass mc = new MainClass();
+		//IntPtr methPtr = typeof(MainClass).GetMethod("Foobar", new Type[]
+{}).MethodHandle.GetFunctionPointer(); // For MS.NET
+		IntPtr methPtr = typeof(MainClass).GetMethod("Foobar", new
+Type[0]).MethodHandle.Value; // For Mono?
+
+		Delegate del = (Delegate)Activator.CreateInstance(delType, new object[] { mc,
+methPtr });
+		del.DynamicInvoke(new object[] {});
+	}
+}
+-- END --
+
+2. Related to the RuntimeMethodHandle implementation is the assignment of
+methPtr in Main(). I can only use RuntimeMethodHandle.Value on Mono.
+
+Actual Results:
+
+** (process:15631): WARNING **: unhandled exception
+System.NullReferenceException: "A null value was found where an object
+instance was required"
+in <0x00228> 00 .MainClass:Main ()
+
+Expected Results:
+
+Foobar!
+
+How often does this happen? 
+
+Always.
+
+Additional Information:
+
+Activator.CreateInstance() is returning null, thus the
+NullReferenceException when the delegate is invoked.
+
+This code works on Microsoft.NET.
+
+If the above code is mangled during the email process (or something silly
+like that), you can download the source from:
+
+http://chemlab.org/~nick/DelegateBuilder.cs
+
+Thanks!