-2

I am stuck in a problem where i am trying to create a Boolean property at run time using Reflection.Emit. I am trying to reproduce the example Link Found Here For String Property , but I am failing to reproduce it for Boolean property, I am missing a clue can someone help me?

Here's the code I tried:

class Program
{
    static void Main(string[] args)
    {
        Type generatedType = newTypeConvert();
        object generetedObject = Activator.CreateInstance(generatedType);
        var x = generetedObject.GetType().GetProperty("CheckBoxColumn").GetValue(generetedObject, null);
        Console.WriteLine(x);
    }
    private static Type newTypeConvert()
    {
        var myDomain   = Thread.GetDomain();
        var myAsmName  = new AssemblyName();
        myAsmName.Name = "MyDynamicAssembly";

        // To generate a persistable assembly, specify AssemblyBuilderAccess.RunAndSave.
        AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(myAsmName,
                                                        AssemblyBuilderAccess.RunAndSave);
        // Generate a persistable single-module assembly.
        ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(myAsmName.Name, myAsmName.Name + ".dll");
        TypeBuilder myTypeBuilder = myModBuilder.DefineType("CustomDynamicClass", TypeAttributes.Public);
        FieldBuilder checkBoxColumnBldr = myTypeBuilder.DefineField("checkBoxColumn", typeof(bool), FieldAttributes.Private);
        PropertyBuilder checkBoxPropBldr = myTypeBuilder.DefineProperty("CheckBoxColumn", System.Reflection.PropertyAttributes.HasDefault, typeof(bool), new Type[] { typeof(bool) });

        // The property set and property get methods require a special set of attributes.
        MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;

        // Define the "get" accessor method for CustomerName.
        MethodBuilder checkBoxGetPropMthdBldr = myTypeBuilder.DefineMethod("get_CheckBoxColumn", getSetAttr, typeof(Boolean), Type.EmptyTypes);
        ILGenerator checkBoxGetIL = checkBoxGetPropMthdBldr.GetILGenerator();
        //checkBoxGetIL.Emit(OpCodes.Ldc_I4_0, bool.FalseString);
        checkBoxGetIL.Emit(OpCodes.Ldarg_0);
        checkBoxGetIL.Emit(OpCodes.Ldfld, checkBoxColumnBldr);
        checkBoxGetIL.Emit(OpCodes.Ret);

        // Define the "set" accessor method for CustomerName.
        MethodBuilder checkBoxSetPropMthdBldr = myTypeBuilder.DefineMethod("set_CheckBoxColumn", getSetAttr, null, new Type[] { typeof(Boolean) });
        ILGenerator checkBoxSetIL = checkBoxSetPropMthdBldr.GetILGenerator();
        //checkBoxSetIL.Emit(OpCodes.Ldc_I4_0, bool.FalseString);
        checkBoxSetIL.Emit(OpCodes.Ldarg_0);
        checkBoxSetIL.Emit(OpCodes.Ldarg_1);
        checkBoxSetIL.Emit(OpCodes.Stfld, checkBoxColumnBldr);
        checkBoxSetIL.Emit(OpCodes.Ret);

        // Last, we must map the two methods created above to our PropertyBuilder to their corresponding behaviors, "get" and "set" respectively. 
        checkBoxPropBldr.SetSetMethod(checkBoxGetPropMthdBldr);
        checkBoxPropBldr.SetSetMethod(checkBoxSetPropMthdBldr);

        Type generatedType = myTypeBuilder.CreateType();

        // Save the assembly so it can be examined with Ildasm.exe, or referenced by a test program.
        myAsmBuilder.Save(myAsmName.Name + ".dll");

        generatedType = myTypeBuilder.CreateType();
        return generatedType;
    }
}

This fails with the following exception:

Unhandled Exception: System.ArgumentException: Property Get method was not found.
   at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
   at Program.Main(String[] args)
AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
  • What's the problem? – Chayim Friedman Jul 30 '18 at 13:32
  • @ChayimFriedman, the Boolean property isn't shown, when i tried the string property it is working normally and a property is shown when I create an instance. It seems I am missing something. – Anthony Semaan Jul 30 '18 at 13:38
  • 1
    When I run that code, it throws a NotSupportedException. Calling `myTypeBuilder.CreateType()` before you call `Save` fixes it though, and the resulting assembly has a type with a Boolean property... – Jon Skeet Jul 30 '18 at 13:44
  • Dear @DaisyShipton, I am sorry I did not copied that part `Type generetedType = myTypeBuilder.CreateType();` of my code, but this will fix it, and here is the part to instantiate an instance `object generetedObject = Activator.CreateInstance(generetedType);`, here I'll edit the post. – Anthony Semaan Jul 30 '18 at 13:48
  • @ArnoldDemian there's definitely a problem in your code... sec, looking... (I can repro it not showing correctly) – Marc Gravell Jul 30 '18 at 13:52
  • @MarcGravell, That's why I'm posting a question regarding the code, I tried the Microsoft example sited in the link and it worked. – Anthony Semaan Jul 30 '18 at 13:55
  • So what are you then doing with `generetedObject`? It would help if you'd present a simple [mcve] to let us reproduce the problem. (It sounds like Marc has now done so, and he's likely to be able to find out what's wrong - but the question would be better if you'd make it clearer. – Jon Skeet Jul 30 '18 at 13:56
  • @DaisyShipton in my opinion this code satisfies the minimal repro – Marc Gravell Jul 30 '18 at 14:03
  • Dear @DaisyShipton, I will try to make it clearer, thank you for your help, and please excuse my lack of knowledge I am still new to all this. – Anthony Semaan Jul 30 '18 at 14:08
  • @MarcGravell: It's definitely pretty close now (better than many). But without knowing what the OP is doing with the object, it still requires some rooting around to see how the bug is exposed. – Jon Skeet Jul 30 '18 at 14:08
  • @ArnoldDemian: Absolutely - the point of giving advice like this isn't to make you feel bad. Quite the contrary - it's to help you (and the site) get better :) – Jon Skeet Jul 30 '18 at 14:08
  • Dear @MarcGravell, thank you for your support, I did a little Console App as sample to demonstrate my error, hope it'll help, I'll edit my post right away. – Anthony Semaan Jul 30 '18 at 14:09
  • 1
    @ArnoldDemian: Now *that's* a good question :) (I'll add the `using` directives and the current output, but we're basically there.) Thanks for your efforts on improving it! – Jon Skeet Jul 30 '18 at 14:17
  • @DaisyShipton thank you for your support. – Anthony Semaan Jul 30 '18 at 14:19

2 Answers2

2

Right; there are multiple bugs:

  1. you need to call SetGetMethod:

    checkBoxPropBldr.SetGetMethod(checkBoxGetPropMthdBldr);
    checkBoxPropBldr.SetSetMethod(checkBoxSetPropMthdBldr);
    
  2. the signatures need to not take indexers

    PropertyBuilder checkBoxPropBldr = myTypeBuilder.DefineProperty("CheckBoxColumn",
            System.Reflection.PropertyAttributes.HasDefault,
            typeof(bool), Type.EmptyTypes);
    

With that; it should work

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Dear @MarcGravell , it also gave me an other error, here it is `System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'` – Anthony Semaan Jul 30 '18 at 14:17
  • Thank you it helped me a lot, I had to add the Emit for getter and setter also, which i commented by mistake. – Anthony Semaan Jul 30 '18 at 14:23
1

Typo, both say SetSet:

checkBoxPropBldr.SetSetMethod(checkBoxGetPropMthdBldr);
checkBoxPropBldr.SetSetMethod(checkBoxSetPropMthdBldr);

should be

checkBoxPropBldr.SetGetMethod(checkBoxGetPropMthdBldr);
checkBoxPropBldr.SetSetMethod(checkBoxSetPropMthdBldr);

With that code your generated class has the property, but only a Set method, so its a write-only property

Thymine
  • 8,775
  • 2
  • 35
  • 47