Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self-referential enum attributes in a C# dynamic assembly

Consider the following code:

    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Enum, AllowMultiple = true)]
    public class TransitionToAttribute : Attribute
    {
      public readonly object Next;
      public TransitionToAttribute(object next)
      {
        Next = next;
      }
    }

    [TransitionToAttribute(DirectedGraph.A)]
    public enum DirectedGraph
    {
      [TransitionToAttribute(DirectedGraph.B)]
      A,

      [TransitionToAttribute(null)]
      B
    }

The code compiles fine. Now I want to define a similar enum in a dynamic assembly with code like:

  AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(
    new AssemblyName("TestAssembly"), AssemblyBuilderAccess.RunAndSave);
  ModuleBuilder mb = ab.DefineDynamicModule("TestModule");
  EnumBuilder eb = mb.DefineEnum("DirectedGraph2", TypeAttributes.Public, typeof(int));
  FieldBuilder fb = eb.DefineLiteral("A", 0);
  FieldBuilder fb2 = eb.DefineLiteral("B", 1);
  eb.SetCustomAttribute(new CustomAttributeBuilder(
    typeof(TransitionToAttribute).GetConstructors().First(), new object[] { ??? }));
  Type created = eb.CreateType();

What is the "???" that I pass to the attribute constructor? "???" needs to be some representation of the "A" literal in the enum I am in the process of defining. I've tried passing fb, fb.GetValue(null), and calling various combinations of Enum.Parse(), Enum.ToObject(), Enum.GetValues(), and other methods but nothing seems to work.

The obvious replacement for ??? is the underlying integer enum value (e.g., 0 for A, 1 for B, etc.), but this doesn't work the way I need it to. At some point, I want to do something like

TransitionToAttribute attr = GetCustomAttribute(...)
Type enumType = attr.Next.GetType();

and determine the enum type that way. This is possible in the first, normally compiled example. But if I pass the underlying enum value to the dynamically created attribute, the type information is lost and enumType is reported as Int32.

like image 797
Peter Winton Avatar asked Jun 13 '26 03:06

Peter Winton


1 Answers

Try calling CreateType before calling SetCustomAttribute (see the sample code for SetCustomAttribute).

Type created = eb.CreateType();
eb.SetCustomAttribute(new CustomAttributeBuilder(
    typeof(TransitionToAttribute).GetConstructors().First(),
    new object[] { Enum.Parse(created, "A") }));
like image 84
ESRogs Avatar answered Jun 14 '26 18:06

ESRogs



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!