[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!