Brief: I have generated dynamically many Enums and saved them in an dynamic Assembly. I have tried to load this Assembly and use its Types(Enums) as Fields of generated struct. Those structs will be save in a diiferent assembly.
But there is a problem during the save-process of the new Assembly(of Structs)
Here is the code I actually use:
public List<Type> CreateEnum()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
AssemblyName aName = new AssemblyName("AssemblyTest");
AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(
aName, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(aName.Name, aName.Name + ".dll");
for (int i = 0; i < list_Datatype_Typ.Count; i++)
{
if (list_SingleValues != null && list_SingleValues[i] != "")
{
if (tmp == eb_count)
{
list_enumBuilder.Add( moduleBuilder.DefineEnum(list_Datatype_Id[i].ToString(), // record a new Enum in the Module (Assembly, contains only one module)
TypeAttributes.Public, list_RealDatatype[i]) );
tmp++; // variable to check if the previous Enum is completed
}
// Check if is a SingleValue
if ((((i < list_Datatype_Id.Count - 1) && (list_Datatype_Id[i] == list_Datatype_Id[i + 1]))
|| ((i > 0) && list_Datatype_Id[i] == list_Datatype_Id[i - 1]))
&& (list_Datatype_Typ[i].ToString() != "ValueRange" && list_Datatype_Typ[i].ToString() != "RecordValueRange" && list_Datatype_Typ[i].ToString() != "none"))
{
list_enumBuilder[eb_count].DefineLiteral(list_Datatype_Typ[i].ToString(), Convert.ChangeType(list_SingleValues[i].ToString(), list_RealDatatype[i]));
// check if those singlevalues with this type were all written
if (((i < list_Datatype_Id.Count-1) && list_Datatype_Id[i] != list_Datatype_Id[i+1]) || (i == list_Datatype_Id.Count - 1))
{
// Create the type and save the assembly.
list_EnumType.Add(list_enumBuilder[eb_count].CreateType());
eb_count++; // At the end of an Enum... let's increment the EnumBuilder_count
}
}
}
}
assemblyBuilder.Save(aName.Name + ".dll"); // Save the Assembly after all the Enum-Types were created
return list_EnumType; // return the list of enum-types
}
public List<Type> CreateStruct()
{
// Create assembly and module
var assemblyName = new AssemblyName("AssemblyLeuze_Record");
var assemblyBuilder = AppDomain.CurrentDomain.
DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
var moduleBuilder = assemblyBuilder.
DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll");
// Find MarshalAsAttribute's constructor by signature, then invoke
var ctorParameters = new Type[] { typeof(UnmanagedType) };
var ctorInfo = typeof(MarshalAsAttribute).GetConstructor(ctorParameters);
var fields = typeof(MarshalAsAttribute).GetFields(BindingFlags.Public | BindingFlags.Instance);
var sizeConst = (from f in fields
where f.Name == "SizeConst"
select f).ToArray();
var marshalAsAttr = new CustomAttributeBuilder(ctorInfo,
new object[] { UnmanagedType.ByValTStr }, sizeConst, new object[] { 5 });
//**************************************************************************************
// Using the Enums.. to test ********************************************
Assembly ass = System.Reflection.Assembly.LoadFrom("AssemblyLeuze.dll");
//Type a = ass.GetType("DT_0_29");
Enum enumObj = (Enum)Activator.CreateInstance(ass.GetType("DT_0_29"));
//enumObj i;
string[] enums = (from type in ass.GetTypes() // get all the Enum-Names (will use it down in the conditions)
select type.Name).ToArray();
for (int i = 0; i < list_Datatype.Count; i++) // Read only recordT datatypes
{
// get all the RecordTs
if (list_Datatype != null && list_Datatype[i] != "" && Convert.ToBoolean(list_IsRecordItem[i].ToString()))
{
if (tmp == tb_count)
{
// Open a new Type for definition
list_typeBuilder.Add( moduleBuilder.DefineType(list_Datatype_Id[i].ToString(),
TypeAttributes.Public |
TypeAttributes.Sealed |
TypeAttributes.ExplicitLayout |
TypeAttributes.Serializable |
TypeAttributes.AnsiClass,
typeof(ValueType)) );
tmp++; // variable to check if the previous Enum is completed
}
// Record the Fields
if (Other Types) // Because of the order in the dataTable, read Datatype_Id instead of Datatype_Typ
{
// ...
}
else if (!(enums.Contains<string>(list_Datatype_Id[i].ToString())))
{
list_FieldBuilder.Add(list_typeBuilder[tb_count].DefineField(
list_Datatype_Id[i], // the name of the struct-Feld
list_RealDatatype[i], // the datatype of the struct-Feld
FieldAttributes.Public));
list_FieldBuilder[fb_count].SetCustomAttribute(marshalAsAttr);
list_FieldBuilder[fb_count].SetOffset(fb_count);
}
fb_count++; // first incrementaton of fb_count
// check if those singlevalues with this type were all written
if (((i < list_Datatype.Count-1) && list_Datatype[i] != list_Datatype[i+1]) || (i == list_Datatype.Count-1))
{
list_StructType.Add(list_typeBuilder[tb_count].CreateType()); // Create the type and save the assembly.
isVal.Add(list_StructType[tb_count].IsValueType); // true
fb_count = 0; // reset fb_count at the end of the struct
list_FieldBuilder.Clear(); // Reset the list of Fields by clearing
tb_count++; // At the end of a Struct... let's increment the EnumBuilder_count
}
}
}
assemblyBuilder.Save(assemblyName.Name + ".dll"); // Save the Assembly after all the Enum-Types were created
return list_StructType; // return a list which contains struct-types
}
Issue: "Here is the error message"
System.TypeLoadException: 'The type' DT_TTT 'of the assembly' AssemblyTest, Version = 0.0.0.0, Culture = neutral, PublicKeyToken = null 'could not be loaded because it contains an object field at Offset 1 that is misaligned or from one Overlapping field that is not an object field. '
I don't know if if due to and error during the loading, or my Assembly containing the Enums were wrong generated, or the is another way to generate those struct.
Thank you.