2015-11-05 61 views
1

使用TypeBuilder(.NET 4.6)API我在運行時創建了Enum對象; w.r.t.動態代碼生成這裏是產率:如何在C#中使用.NET表達式API爲枚舉創建賦值表達式

public enum WorkflowModelProperty 
    { 
     WorkflowModelDate = 1, 
     WorkflowModelTime = 2, 
     WorkflowModelHeader = 3, 
     WorkflowModelTitle = 4, 
     WorkflowModelID  = 5, 
     WorkflowModelOntologyRoot = 6, 
    } 

這裏是用來生成枚舉對象的代碼:

// Create a dynamic assembly in the current application domain and allow it to be executed. 

var dynamicAssemblyName = new AssemblyName(theAssemblyName); 
var assemlbyBuilderFactory = await CurrentAppDomain.DefineDynamicAssembly, dynamicAssemblyName, BuilderAccess); 

var moduleBuilderFactory = await assemlbyBuilderFactory.DefineDynamicModule(theLibraryModuleName, dynamicAssemblyName.Name + DLLPrefix); 

TypeBuilder enumTypeBuilderFactory = moduleBuilderFactory.DefineType(theEnumDefinitionName, TypeAttributes.Public, typeof (Enum), null); 

enumTypeBuilderFactory?.DefineField("value__", typeof(int), FieldAttributes.Private | FieldAttributes.SpecialName); 

這裏是添加字段成員到枚舉TypeBuilder對象的代碼:

EnumHostInfoSetCache = EnumHostInfoSetCacheBuilder.ToImmutable(); 

// Okay we need to check to see if the internal states validate the DSL model passed into us. 

enumHostInfoSet = EnumHostInfoSetCache.SingleOrDefault(
    enumHostEntry => 
     (enumHostEntry.Value.GetValueOrDefault().EnumDefintionName == 
     localTypeDefinitionDSL.TheEnumDefinitionName)).Value; 

var enumBuilder = await enumHostInfoSet.GetValueOrDefault().EnumTypeBuilder; 

EnumFieldBuilderMaterializer = EnumFieldBuilderConnectedObserver?. 
          SubscribeOn(Scheduler.CurrentThread).Subscribe(
           delegate(Tuple<string, TEnumBaseType> enumFieldMetadata) 
           { 
            try 
            { 
             var enumFieldName = enumFieldMetadata.GetEnumFieldMemberName(); 
             var enumFieldValue = enumFieldMetadata.GetEnumFieldMemberValue(); 

             // Code Generate the Enum Field, thus creating a literal definition 
             var enumFieldBuilder = enumBuilder.DefineField(enumFieldName, enumBuilder, 
              FieldAttributes.Public | FieldAttributes.Literal | FieldAttributes.Static); 

             // Set the Constant value on 
             enumFieldBuilder.SetConstant(enumFieldValue); 

             // Okay, at this point the Enum Metadata DSL Model is hooked-up to our source here and is not connected to 
             // the Hot Observable source here in the Agent; as we push data into memory the Model should load itself. 

             EnumFieldBuilderCacheBuilder?.Add(enumFieldName, enumFieldBuilder); 
            } 
            catch (Exception e) 
            { 
             throw new ProtoNexusAPIException(e.Message); 
            } 
           }, 
           delegate(Exception exception) 
           { 
            CodeGenExceptionHandler(exception); 
           }, 

在這一點上我已經得到了產生枚舉類型的全烤實例。現在,我想創建對枚舉類型的動態生成實例的分配 - 這裏的代碼:

delegate() // OnCompleted() Implementation! 
           { 
            // Step 0: Prepare for generation of Dynamic Enum Assignment via Expression APIs 

            var codeForEnumType = enumBuilder.CreateType(); 
            var enumInstance  = Activator.CreateInstance(Enum.GetUnderlyingType(codeForEnumType)); 
            var enumInstanceX  = Activator.CreateInstance(codeForEnumType); 
            var recordOfEnumFields = enumBuilder.DeclaredFields; 

            // Okay let's set-up for dynamic materialization of Enum Assignment Expression code: 

            try 
            { 
             // Experimental code for learning and teaching... 

             var rightSideExp = Enum.ToObject(codeForEnumType, 2); // I know I can get to this ordinal value 

             // Step 1: Enum has been created and is ready for use. 
             var enumCode = Expression.Variable(enumBuilder, "enumCode"); 
             // Step 2: Okay we are ready to make the Assignment via the Expression.Assign API. We can set this up a number of ways 
             var enumAssignmentSource = Expression.Constant(rightSideExp); // This is the value we want to assign 
             var enumRightHandSideA = Expression.Constant(Enum.ToObject(codeForEnumType, 1), codeForEnumType); 
             //var enumRightHandSideB = Expression.Constant(3, codeForEnumType); // This DOES NOT WORK! - Argument does not Match! 
             var enumRightHandSideC = Expression.Constant(enumInstanceX, codeForEnumType); 
             // Step 3: 
             var workFlowDisplayCommand = Expression.Assign(enumCode, enumRightHandSideA); // DOES NOT WORK - Argument does not Match! 
             workFlowDisplayCommand = Expression.Assign(enumCode, enumRightHandSideC);  // DOES NOT WORK 
             workFlowDisplayCommand = Expression.Assign(enumCode, enumAssignmentSource); // DOES NOT WORK 
            } 
            catch (Exception e) 
            { 
             Debug.WriteLine(e.Message); 
            } 

            localTypeDefinitionDSL.SetEnumType(codeForEnumType, ref recordOfEnumFields); 
            localTypeDefinitionDSL.SetEnumTypeInstance(enumInstance); 

            if (EnumFieldBuilderCacheBuilder != null) 
            { 
             try 
             { 
              // Setup the Rx HOT Subscription: 
              // Step 1: Load-up our Immutable Collection 
              EnumFieldBuilderCache = EnumFieldBuilderCacheBuilder?.ToImmutable(); 
              // Step 2: Create our Observable Source 
              EnumFieldBuilderCollectionSource = 
               EnumFieldBuilderCache?.ToObservable(Scheduler.CurrentThread); 
              // Step 3: Convert the Collection Source to a Hot Observable 
              EnumFieldBuilderSubscriptionSource = 
               EnumFieldBuilderCollectionSource?.Publish(); 
              EnumFieldBuilderSubscriptionSource.ObserveOn(Scheduler.CurrentThread); 
              localTypeDefinitionDSL.LoadFieldBuilderSubscription(
               EnumFieldBuilderSubscriptionSource); 
             } 
             catch (Exception e) 
             { 
              throw new ApplicationException(e.Message); 
             } 
            } 

            EnumFieldBuilderMaterializer?.Dispose(); 
           }); 

下面是運行時錯誤消息:類型的表達式WorkflowMessagingCommands'不能用於分配鍵入「 WorkflowMessagingCommands'

我錯過了什麼?

回答

0

在您的代碼的第一步中,您必須更改方法的第一個參數Expression.Variable。此方法的第一個參數應該是您的類型,並且您沒有爲變量創建傳遞正確的類型。

您必須使用這樣的:

var enumCode = Expression.Variable(codeForEnumType, "enumCode"); 
+0

是啊,我知道它是一個輕微的疏忽 - 謝謝你阿爾貝託那確實解決問題。 –

+0

僅供參考 - 當我使用** EnumBuilder **代替** TypeBuilder **時,此代碼不起作用。 –

相關問題