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'
我錯過了什麼?
是啊,我知道它是一個輕微的疏忽 - 謝謝你阿爾貝託那確實解決問題。 –
僅供參考 - 當我使用** EnumBuilder **代替** TypeBuilder **時,此代碼不起作用。 –