0

I've been tasked to generate a dynamic enumeration that has database driven values to alleviate recompiling and deployment of the Enum object when new values are added. The enumeration will exist as part of a internally consumed service.

The natural and most obvious advantage of this approach I suppose would be that anyone having need to consume the service would know immediately what values are available during development.

I'm not a big fan of this approach but I am up for the challenge.

The following code produces a RuntimeType but it throws an error on every attempt I've made in effort to cast this as an Enum.

    public Enum GenerateDynamicSmsEnumValues<T>(Dictionary<int,string> enumValues)
    {
        try
        {
            //    Create Base Assembly Objects
            AppDomain appDomain = AppDomain.CurrentDomain;
            AssemblyName asmName = new AssemblyName("SmsApplicationID");
            AssemblyBuilder asmBuilder = appDomain.
              DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Run);

            //    Create Module and Enumeration Builder Objects
            ModuleBuilder modBuilder = asmBuilder.
              DefineDynamicModule("SmsApplicationID");
            EnumBuilder enumBuilder = modBuilder.
              DefineEnum("SmsApplicationID", TypeAttributes.Public, typeof(int));

            //  Build enumerations
            foreach (var pair in enumValues)
                enumBuilder.DefineLiteral(pair.Value, pair.Key);

            var returnType = enumBuilder.CreateType();
            var enm = (object)returnType;

            return (Enum)enm; // <-- Error Thrown Here
        }
        catch(Exception ex)
        {
            return null;
        }

If I inspect the object before the attempted cast the IsEnum attribute is set to true so I believe I have the object I need.

I just cannot figure out how to properly cast it to an Enum type to be used by any code leveraging the method.

I have also tried this approach using a Generic Template method but the problem is pretty much the same.

How can I cast this to an Enum object???

Mark
  • 1,667
  • 2
  • 24
  • 51
  • what is the exception? – Ehsan Sajjad Dec 19 '17 at 18:48
  • @EhsanSajjad Unable to cast object of type 'System.RuntimeType' to type 'System.Enum'. – Mark Dec 19 '17 at 18:49
  • You can't cast it to Enum because `enm` is a Type object. An instance of the type would be castable to Enum. But what is the utility of a dynamically generated enum type here? You can't refer to it by name in any program text. The names have to be looked up dynamically. Why not just maintain some mappings that are stored in and loaded from the database? – Mike Zboray Dec 19 '17 at 19:09
  • You've got the enum's type, now you need to create an instance of that type by using Activator.CreateInstance(Type type) –  Dec 19 '17 at 19:09
  • @mikez I agree and I stated that I wasn't a huge proponent of this approach but it is what I've been tasked to do. I believe the general idea is to create an assembly and reference the assembly to acquire the Enum for consumers of the service. When new values are added; only the assembly reference would require an update. – Mark Dec 20 '17 at 11:23
  • @Will could you kindly provide an example of your proposed approach? I tried it as var t = Activator.CreateInstance(typeof(SmsApplicationID)); with SmsApplicationID being my enumeration object. No errors were thrown but the enumeration is empty. – Mark Dec 20 '17 at 11:26
  • `Activator.CreateInstance(returnType);` I believe. It's easy to verify when you're sitting in front of your IDE, debugging your code. Inspect the type of `returnType`. I believe it is RuntimeType, which is an internal (to the framework) implementation of System.Type. Now go to the documentation and look at `Activator.CreateInstance`, It should have an overload that takes a Type object. Use that to create an instance of your enumeration type. It will be the default value of that enum. I don't know if that's useful to you, in the end. –  Dec 20 '17 at 14:21
  • If it isn't, there are many methods on the Enum type (again, check the docs!) that take Type objects and provide you various enum goodnesses. Anyhow, at some point you'll be able to say "I have the type of an enum. I need to get an instance of that enum that _______", which is answerable, and has either been already asked, or you can ask it. –  Dec 20 '17 at 14:23

0 Answers0