diff options
author | Alexander Kyte <alexmkyte@gmail.com> | 2017-11-28 18:44:38 +0300 |
---|---|---|
committer | Ludovic Henry <luhenry@microsoft.com> | 2017-11-28 18:44:38 +0300 |
commit | 0927d51418c20694046b25f84989b97eda0b6ad6 (patch) | |
tree | fb0338e5c615741a1fd4a3b08c3e516627d66ddf /mcs/class/corlib | |
parent | b3fad3f0f899d3f28becf3f20843de8b84c62d98 (diff) |
[runtime] Implement a few ModuleBuilder getters (#5787)
* [runtime] Implement a few broken getters on ModuleBuilder
* [runtime] Implement ModuleBuilder.GetCustomAttributes
* [runtime] Test GetMethods, GetCustomAttributes, and GetFields for ModuleBuilder
* [runtime] Specify and test use of typebuilders with Custom Attributes + add more tests
Diffstat (limited to 'mcs/class/corlib')
3 files changed, 258 insertions, 8 deletions
diff --git a/mcs/class/corlib/System.Reflection.Emit/CustomAttributeBuilder.cs b/mcs/class/corlib/System.Reflection.Emit/CustomAttributeBuilder.cs index 0bb724ad8c4..a0f11bd20cd 100644 --- a/mcs/class/corlib/System.Reflection.Emit/CustomAttributeBuilder.cs +++ b/mcs/class/corlib/System.Reflection.Emit/CustomAttributeBuilder.cs @@ -46,6 +46,11 @@ namespace System.Reflection.Emit { public class CustomAttributeBuilder : _CustomAttributeBuilder { ConstructorInfo ctor; byte[] data; + object [] args; + PropertyInfo [] namedProperties; + object [] propertyValues; + FieldInfo [] namedFields; + object [] fieldValues; internal ConstructorInfo Ctor { get {return ctor;} @@ -57,7 +62,20 @@ namespace System.Reflection.Emit { [MethodImplAttribute(MethodImplOptions.InternalCall)] static extern byte[] GetBlob(Assembly asmb, ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues, FieldInfo[] namedFields, object[] fieldValues); - + + internal object Invoke () + { + object result = ctor.Invoke (args); + + for (int i=0; i < namedFields.Length; i++) + namedFields [i].SetValue (result, fieldValues [i]); + + for (int i=0; i < namedProperties.Length; i++) + namedProperties [i].SetValue (result, propertyValues [i]); + + return result; + } + internal CustomAttributeBuilder( ConstructorInfo con, byte[] binaryAttribute) { if (con == null) throw new ArgumentNullException ("con"); @@ -140,6 +158,12 @@ namespace System.Reflection.Emit { FieldInfo [] namedFields, object [] fieldValues) { ctor = con; + args = constructorArgs; + this.namedProperties = namedProperties; + this.propertyValues = propertyValues; + this.namedFields = namedFields; + this.fieldValues = fieldValues; + if (con == null) throw new ArgumentNullException ("con"); if (constructorArgs == null) diff --git a/mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.cs b/mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.cs index f629f8a3861..8744b4a4581 100644 --- a/mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.cs +++ b/mcs/class/corlib/System.Reflection.Emit/ModuleBuilder.cs @@ -1169,32 +1169,55 @@ namespace System.Reflection.Emit { public override object[] GetCustomAttributes (bool inherit) { - return base.GetCustomAttributes (inherit); + return GetCustomAttributes (null, inherit); } public override object[] GetCustomAttributes (Type attributeType, bool inherit) { - return base.GetCustomAttributes (attributeType, inherit); + if (cattrs == null || cattrs.Length == 0) + return Array.Empty<object> (); + + if (attributeType is TypeBuilder) + throw new InvalidOperationException ("First argument to GetCustomAttributes can't be a TypeBuilder"); + + List<object> results = new List<object> (); + for (int i=0; i < cattrs.Length; i++) { + Type t = cattrs [i].Ctor.GetType (); + + if (t is TypeBuilder) + throw new InvalidOperationException ("Can't construct custom attribute for TypeBuilder type"); + + if (attributeType == null || attributeType.IsAssignableFrom (t)) + results.Add (cattrs [i].Invoke ()); + } + + return results.ToArray (); } public override FieldInfo GetField (string name, BindingFlags bindingAttr) { - return base.GetField (name, bindingAttr); + if (global_type_created == null) + throw new InvalidOperationException ("Module-level fields cannot be retrieved until after the CreateGlobalFunctions method has been called for the module."); + return global_type_created.GetField (name, bindingAttr); } public override FieldInfo[] GetFields (BindingFlags bindingFlags) { - return base.GetFields (bindingFlags); + if (global_type_created == null) + throw new InvalidOperationException ("Module-level fields cannot be retrieved until after the CreateGlobalFunctions method has been called for the module."); + return global_type_created.GetFields (bindingFlags); } public override MethodInfo[] GetMethods (BindingFlags bindingFlags) { - return base.GetMethods (bindingFlags); + if (global_type_created == null) + throw new InvalidOperationException ("Module-level methods cannot be retrieved until after the CreateGlobalFunctions method has been called for the module."); + return global_type_created.GetMethods (bindingFlags); } public override int MetadataToken { get { - return base.MetadataToken; + return get_MetadataToken (this); } } } diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/ModuleBuilderTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/ModuleBuilderTest.cs index e2574908f45..c1ae91971f9 100644 --- a/mcs/class/corlib/Test/System.Reflection.Emit/ModuleBuilderTest.cs +++ b/mcs/class/corlib/Test/System.Reflection.Emit/ModuleBuilderTest.cs @@ -116,7 +116,6 @@ namespace MonoTests.System.Reflection.Emit } [Test] - [Category("NotWorking")] public void TestGlobalMethods () { AssemblyBuilder builder = genAssembly (); @@ -859,5 +858,209 @@ namespace MonoTests.System.Reflection.Emit Assert.AreEqual ("t1&", module.GetType ("t1&").FullName); Assert.AreEqual ("t1[]&", module.GetType ("t1[]&").FullName); } + + [AttributeUsage(AttributeTargets.All)] + public class MyAttribute : Attribute { + public String Contents; + public MyAttribute (String contents) + { + this.Contents = contents; + } + } + + [Test] + public void GetMethodsBeforeInstantiation () + { + AssemblyBuilder assm = AssemblyBuilder.DefineDynamicAssembly (new AssemblyName ("Name"), AssemblyBuilderAccess.Run); + ModuleBuilder module = assm.DefineDynamicModule ("Module"); + + // Added to make sure fields and methods not mixed up by getters + FieldBuilder fieldBuilder = module.DefineInitializedData ("GlobalField", new byte[4], FieldAttributes.Public); + + MethodBuilder method = module.DefinePInvokeMethod ("printf", "libc.so", + MethodAttributes.PinvokeImpl | MethodAttributes.Static | MethodAttributes.Public, + CallingConventions.Standard, typeof (void), new Type [] { typeof (string) }, CallingConvention.Winapi, + CharSet.Auto); + method.SetImplementationFlags (MethodImplAttributes.PreserveSig | + method.GetMethodImplementationFlags ()); + + module.CreateGlobalFunctions (); + + // Make sure method is defined, but field is not + Assert.AreEqual (1, module.GetMethods (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).Length); + } + + [Test] + public void GetFieldsBeforeInstantiation () + { + AssemblyBuilder assm = AssemblyBuilder.DefineDynamicAssembly (new AssemblyName ("Name"), AssemblyBuilderAccess.Run); + ModuleBuilder module = assm.DefineDynamicModule ("Module"); + FieldBuilder fieldBuilder = module.DefineInitializedData ("GlobalField", new byte[4], FieldAttributes.Public); + module.CreateGlobalFunctions (); + + var fieldG = module.GetField (fieldBuilder.Name); + Assert.IsNotNull (fieldG); + Assert.AreEqual (1, module.GetFields (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).Length); + } + + [Test] + public void GetCustomAttributesBeforeInstantiation () + { + AssemblyBuilder assm = AssemblyBuilder.DefineDynamicAssembly (new AssemblyName ("Name"), AssemblyBuilderAccess.Run); + ModuleBuilder module = assm.DefineDynamicModule ("Module"); + module.CreateGlobalFunctions (); + + ConstructorInfo ctor = typeof(MyAttribute).GetConstructor (new Type [] {typeof(String)}); + ctor.GetHashCode (); + CustomAttributeBuilder cab = new CustomAttributeBuilder (ctor, new object [] {"hi"}); + module.SetCustomAttribute (cab); + + Assert.AreEqual (1, module.GetCustomAttributes (false).Length); + Assert.AreEqual (typeof (MyAttribute), ((MyAttribute) module.GetCustomAttributes (false)[0]).GetType ()); + Assert.AreEqual ("hi", ((MyAttribute) module.GetCustomAttributes (false)[0]).Contents); + } + + [Test] + public void GetCustomAttributesIgnoresArg () + { + AssemblyBuilder assm = AssemblyBuilder.DefineDynamicAssembly (new AssemblyName ("Name"), AssemblyBuilderAccess.Run); + ModuleBuilder module = assm.DefineDynamicModule ("Module"); + module.CreateGlobalFunctions (); + + ConstructorInfo ctor = typeof(MyAttribute).GetConstructor (new Type [] {typeof(String)}); + ctor.GetHashCode (); + CustomAttributeBuilder cab = new CustomAttributeBuilder (ctor, new object [] {"hi"}); + module.SetCustomAttribute (cab); + + var first = module.GetCustomAttributes (false); + var second = module.GetCustomAttributes (true); + + Assert.AreEqual (first.Length, second.Length); + + for (int i=0; i < first.Length; i++) + Assert.AreEqual (first [i].GetType (), second [i].GetType ()); + + Assert.AreEqual ("hi", ((MyAttribute) first [0]).Contents); + Assert.AreEqual ("hi", ((MyAttribute) second [0]).Contents); + } + + [Test] + public void GetCustomAttributesThrowsUnbakedAttributeType () + { + AssemblyBuilder assm = AssemblyBuilder.DefineDynamicAssembly (new AssemblyName ("Name"), AssemblyBuilderAccess.Run); + ModuleBuilder module = assm.DefineDynamicModule ("Module"); + TypeBuilder tb = module.DefineType ("foo"); + module.CreateGlobalFunctions (); + + ConstructorInfo ctor = typeof(MyAttribute).GetConstructor (new Type [] {typeof(String)}); + ctor.GetHashCode (); + CustomAttributeBuilder cab = new CustomAttributeBuilder (ctor, new object [] {"hi"}); + module.SetCustomAttribute (cab); + + try { + module.GetCustomAttributes (tb, false); + } + catch (InvalidOperationException e) { + // Correct behavior + return; + } + + Assert.Fail ("Supposed to throw"); + } + + [Test] + public void GetExternalTypeBuilderCAttr () + { + AssemblyBuilder assm = AssemblyBuilder.DefineDynamicAssembly (new AssemblyName ("Name"), AssemblyBuilderAccess.Run); + ModuleBuilder module = assm.DefineDynamicModule ("Module"); + + ModuleBuilder module_two = assm.DefineDynamicModule ("ModuleTwo"); + TypeBuilder tb = module_two.DefineType ("foo"); + + ConstructorInfo ctor = tb.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); + CustomAttributeBuilder cab = new CustomAttributeBuilder (ctor, Array.Empty<object> ()); + + // Set the custom attribute to have a type builder from another module + module.SetCustomAttribute (cab); + + module.CreateGlobalFunctions (); + + try { + module.GetCustomAttributes (false); + } + catch (NotSupportedException e) { + // Correct behavior + return; + } + Assert.Fail ("Supposed to throw"); + } + + [Test] + public void GetFieldsNoGlobalType () + { + AssemblyBuilder assm = AssemblyBuilder.DefineDynamicAssembly (new AssemblyName ("Name"), AssemblyBuilderAccess.Run); + ModuleBuilder module = assm.DefineDynamicModule ("Module"); + FieldBuilder fieldBuilder = module.DefineInitializedData ("GlobalField", new byte[4], FieldAttributes.Public); + + try { + module.GetFields (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance); + } + catch (InvalidOperationException e) { + // Correct behavior + return; + } + Assert.Fail ("Supposed to throw"); + } + + [Test] + public void GetFieldNoGlobalType () + { + AssemblyBuilder assm = AssemblyBuilder.DefineDynamicAssembly (new AssemblyName ("Name"), AssemblyBuilderAccess.Run); + ModuleBuilder module = assm.DefineDynamicModule ("Module"); + FieldBuilder fieldBuilder = module.DefineInitializedData ("GlobalField", new byte[4], FieldAttributes.Public); + + try { + module.GetField (fieldBuilder.Name); + } + catch (InvalidOperationException e) { + // Correct behavior + return; + } + Assert.Fail ("Supposed to throw"); + } + + [Test] + public void GetMethodsNoGlobalType () + { + AssemblyBuilder assm = AssemblyBuilder.DefineDynamicAssembly (new AssemblyName ("Name"), AssemblyBuilderAccess.Run); + ModuleBuilder module = assm.DefineDynamicModule ("Module"); + FieldBuilder fieldBuilder = module.DefineInitializedData ("GlobalField", new byte[4], FieldAttributes.Public); + + MethodBuilder method = module.DefinePInvokeMethod ("printf", "libc.so", + MethodAttributes.PinvokeImpl | MethodAttributes.Static | MethodAttributes.Public, + CallingConventions.Standard, typeof (void), new Type [] { typeof (string) }, CallingConvention.Winapi, + CharSet.Auto); + method.SetImplementationFlags (MethodImplAttributes.PreserveSig | + method.GetMethodImplementationFlags ()); + + try { + module.GetMethods (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance); + } + catch (InvalidOperationException e) { + // Correct behavior + return; + } + Assert.Fail ("Supposed to throw"); + } + + [Test] + public void GetMetadataToken () + { + AssemblyBuilder assm = AssemblyBuilder.DefineDynamicAssembly (new AssemblyName ("Name"), AssemblyBuilderAccess.Run); + ModuleBuilder module = assm.DefineDynamicModule ("Module"); + module.CreateGlobalFunctions (); + Assert.AreEqual (0, module.MetadataToken); + } + } } |