From 6aea7e6ccc8e8fcc94821ab0f99c6b0b0ec00da0 Mon Sep 17 00:00:00 2001 From: Milos Kotlar Date: Thu, 17 Aug 2023 13:08:23 +0200 Subject: [PATCH 1/5] Use the image's ALC instead of the default one if exists --- src/mono/mono/metadata/custom-attrs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mono/mono/metadata/custom-attrs.c b/src/mono/mono/metadata/custom-attrs.c index 8fc9f47daf0af9..d82db6a960e7e4 100644 --- a/src/mono/mono/metadata/custom-attrs.c +++ b/src/mono/mono/metadata/custom-attrs.c @@ -234,7 +234,10 @@ static MonoType* cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error) { ERROR_DECL (inner_error); + // Use the image's ALC instead of the default one if exists MonoAssemblyLoadContext *alc = mono_image_get_alc (image); + if (!alc) + alc = mono_alc_get_default (); MonoType *t = mono_reflection_type_from_name_checked (n, alc, image, inner_error); if (!t) { mono_error_set_type_load_name (error, g_strdup(n), NULL, From f8b880b3dd2dfcbd360ae3554d341f14cbc6c98a Mon Sep 17 00:00:00 2001 From: Milos Kotlar Date: Fri, 18 Aug 2023 10:43:01 +0200 Subject: [PATCH 2/5] Init module's image ALC --- src/mono/mono/metadata/custom-attrs.c | 3 --- src/mono/mono/metadata/sre.c | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/metadata/custom-attrs.c b/src/mono/mono/metadata/custom-attrs.c index d82db6a960e7e4..8fc9f47daf0af9 100644 --- a/src/mono/mono/metadata/custom-attrs.c +++ b/src/mono/mono/metadata/custom-attrs.c @@ -234,10 +234,7 @@ static MonoType* cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error) { ERROR_DECL (inner_error); - // Use the image's ALC instead of the default one if exists MonoAssemblyLoadContext *alc = mono_image_get_alc (image); - if (!alc) - alc = mono_alc_get_default (); MonoType *t = mono_reflection_type_from_name_checked (n, alc, image, inner_error); if (!t) { mono_error_set_type_load_name (error, g_strdup(n), NULL, diff --git a/src/mono/mono/metadata/sre.c b/src/mono/mono/metadata/sre.c index de94e8c4bf9a3b..3f47f9e84d008e 100644 --- a/src/mono/mono/metadata/sre.c +++ b/src/mono/mono/metadata/sre.c @@ -1289,6 +1289,7 @@ image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *e * determined at assembly save time. */ /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */ + MonoAssemblyLoadContext *alc = mono_alc_get_default (); MonoStringHandle abname = MONO_HANDLE_NEW_GET (MonoString, ab, name); char *name = mono_string_handle_to_utf8 (abname, error); return_val_if_nok (error, FALSE); @@ -1300,6 +1301,7 @@ image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *e } MonoDynamicAssembly *dynamic_assembly = MONO_HANDLE_GETVAL (ab, dynamic_assembly); image = mono_dynamic_image_create (dynamic_assembly, name, fqname); + image->image.alc = alc; MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoReflectionModule, moduleb), image, MonoImage*, &image->image); MONO_HANDLE_SETVAL (moduleb, dynamic_image, MonoDynamicImage*, image); From 6aa32b21f9d655abdef6c29d01b3802eaeffcd21 Mon Sep 17 00:00:00 2001 From: Milos Kotlar Date: Fri, 18 Aug 2023 11:42:42 +0200 Subject: [PATCH 3/5] Add runtime test for dynamic objects --- .../Loader/CustomAttributes/DynamicObjects.cs | 107 ++++++++++++++++++ .../CustomAttributes/DynamicObjects.csproj | 9 ++ 2 files changed, 116 insertions(+) create mode 100644 src/tests/Loader/CustomAttributes/DynamicObjects.cs create mode 100644 src/tests/Loader/CustomAttributes/DynamicObjects.csproj diff --git a/src/tests/Loader/CustomAttributes/DynamicObjects.cs b/src/tests/Loader/CustomAttributes/DynamicObjects.cs new file mode 100644 index 00000000000000..1aeb30645ba762 --- /dev/null +++ b/src/tests/Loader/CustomAttributes/DynamicObjects.cs @@ -0,0 +1,107 @@ +using System; +using System.Resources; +using System.Reflection; +using System.Reflection.Emit; +using System.ComponentModel.DataAnnotations; +using System.Linq; + +using Xunit; + +#nullable disable + +namespace DynamicObjects { + public class M { + public const string ObjectRequiredMessage = "some string"; + public static int Main() { + var instance = createObject(); + var attrs = instance.GetType().GetProperty("prop1").GetCustomAttributes(); + + Assert.True(attrs.Count() == 2); + Assert.Equal(attrs.ElementAt(0).ToString(), "System.ComponentModel.DataAnnotations.DisplayAttribute"); + Assert.Equal(attrs.ElementAt(1).ToString(), "System.ComponentModel.DataAnnotations.RequiredAttribute"); + Assert.Equal(typeof(RequiredAttribute), attrs.ElementAt(1).GetType()); + Assert.Equal(ObjectRequiredMessage, ((RequiredAttribute)attrs.ElementAt(1)).FormatErrorMessage("abc")); + + Console.WriteLine("Success"); + return 100; + } + + public static object createObject () { + var an = new AssemblyName { Name = "TempAssembly" ,Version = new Version(1, 0, 0, 0) }; + var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run); + var moduleBuilder = assemblyBuilder.DefineDynamicModule("TempWorkflowAssembly.dll"); + var tb = moduleBuilder.DefineType("namespace.myclass" + , TypeAttributes.Public | + TypeAttributes.Class | + TypeAttributes.AnsiClass | + TypeAttributes.BeforeFieldInit + , typeof(object)); + + FieldBuilder fb = tb.DefineField("_prop1", + typeof(string), + FieldAttributes.Private); + + var pb = tb.DefineProperty("prop1", PropertyAttributes.HasDefault, typeof(string), null); + MethodAttributes getSetAttr = + MethodAttributes.Public | MethodAttributes.SpecialName | + MethodAttributes.HideBySig; + + // Define the "get" accessor method for prop1. + MethodBuilder custNameGetPropMthdBldr = + tb.DefineMethod("get_prop1", + getSetAttr, + typeof(string), + Type.EmptyTypes); + + ILGenerator custNameGetIL = custNameGetPropMthdBldr.GetILGenerator(); + + custNameGetIL.Emit(OpCodes.Ldarg_0); + custNameGetIL.Emit(OpCodes.Ldfld, fb); + custNameGetIL.Emit(OpCodes.Ret); + + // Define the "set" accessor method for prop1. + MethodBuilder custNameSetPropMthdBldr = + tb.DefineMethod("set_prop1", + getSetAttr, + null, + new Type[] { typeof(string) }); + + ILGenerator custNameSetIL = custNameSetPropMthdBldr.GetILGenerator(); + + custNameSetIL.Emit(OpCodes.Ldarg_0); + custNameSetIL.Emit(OpCodes.Ldarg_1); + custNameSetIL.Emit(OpCodes.Stfld, fb); + custNameSetIL.Emit(OpCodes.Ret); + + // Last, we must map the two methods created above to our PropertyBuilder to + // their corresponding behaviors, "get" and "set" respectively. + pb.SetGetMethod(custNameGetPropMthdBldr); + pb.SetSetMethod(custNameSetPropMthdBldr); + + + ///create display attribute + var dat = typeof(DisplayAttribute); + CustomAttributeBuilder CAB = new CustomAttributeBuilder(dat.GetConstructor(new Type[0]), + new object[0], + new PropertyInfo[1] { dat.GetProperty(nameof(DisplayAttribute.Name))}, + new object[] { "property 1"}); + pb.SetCustomAttribute(CAB); + + // //create required attribute + var rat = typeof(RequiredAttribute); + CustomAttributeBuilder CABR = new CustomAttributeBuilder(rat.GetConstructor(new Type[0]), + new object[0], + new PropertyInfo[2] { rat.GetProperty(nameof(RequiredAttribute.ErrorMessageResourceType)),rat.GetProperty(nameof(RequiredAttribute.ErrorMessageResourceName))}, + new object[] {typeof(ValidationErrors), "ObjectRequired" }); + pb.SetCustomAttribute(CABR); + + var objectType = tb.CreateType(); + return Activator.CreateInstance(objectType); + } + } + + public class ValidationErrors { + public static string ObjectRequired => M.ObjectRequiredMessage; + } + +} \ No newline at end of file diff --git a/src/tests/Loader/CustomAttributes/DynamicObjects.csproj b/src/tests/Loader/CustomAttributes/DynamicObjects.csproj new file mode 100644 index 00000000000000..3e62bfd677e86a --- /dev/null +++ b/src/tests/Loader/CustomAttributes/DynamicObjects.csproj @@ -0,0 +1,9 @@ + + + Exe + + + + + + From 10162538aaf4f7a432cc5632157858be78103f45 Mon Sep 17 00:00:00 2001 From: Milos Kotlar Date: Fri, 18 Aug 2023 11:45:26 +0200 Subject: [PATCH 4/5] Fix lint --- src/tests/Loader/CustomAttributes/DynamicObjects.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/Loader/CustomAttributes/DynamicObjects.cs b/src/tests/Loader/CustomAttributes/DynamicObjects.cs index 1aeb30645ba762..5b232d83eba3bb 100644 --- a/src/tests/Loader/CustomAttributes/DynamicObjects.cs +++ b/src/tests/Loader/CustomAttributes/DynamicObjects.cs @@ -104,4 +104,4 @@ public class ValidationErrors { public static string ObjectRequired => M.ObjectRequiredMessage; } -} \ No newline at end of file +} From 9b2677c959f64c0af99e04c082588593086158fa Mon Sep 17 00:00:00 2001 From: Milos Kotlar Date: Fri, 18 Aug 2023 18:04:49 +0200 Subject: [PATCH 5/5] Disable test on platforms that don't support dynamic code generation --- src/tests/issues.targets | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 22178e4b3b506d..bdccec81ac1f49 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -1177,6 +1177,10 @@ + + + Dynamic code generation is not supported on this platform +