我正在尝试使用CodeDom创建一个复杂的对象。现在我对创建简单对象没有任何问题,例如:
public class MyClass
{
public FirstName {get; set;}
public LastName {get; set;}
}
public class Subclass
{
public string SubProperty {get; set;}
}
但是我在创建以下内容时遇到了一些麻烦:
public class MyClass
{
public string FirstName {get; set;}
public string LastName {get; set;}
public Subclass[] SubClasses {get; set;}
}
这是我目前的实施。
public class cls_Code_Generator
{
private CodeNamespace CodeNamespace { get; set; }
private JSchema JsonSchema { get; set; }
public cls_Code_Generator()
{
CodeNamespace = new CodeNamespace("GeneratedCode");
CodeNamespace.Imports.Add(new CodeNamespaceImport("System"));
}
public Assembly CreateType(JSchema schema)
{
JsonSchema = schema;
CodeTypeDeclaration CodeType = new CodeTypeDeclaration();
CodeType.Name = "RuntimeType";
CodeType.IsClass = true;
CodeType.Attributes = MemberAttributes.Public;
CodeNamespace.Types.Add(CodeType);
CodeType = GetFields(CodeType);
CodeCompileUnit CodeUnit = new CodeCompileUnit();
CodeUnit.ReferencedAssemblies.AddRange(GetReferenceList());
CodeUnit.Namespaces.Add(CodeNamespace);
return CreateTypeInMemory(CodeUnit);
}
private Assembly CreateTypeInMemory(CodeCompileUnit codeUnit)
{
Assembly CompiledAssembly = null;
CompilerParameters CompilerParams = new CompilerParameters();
CompilerParams.ReferencedAssemblies.AddRange(new[] { "System.dll" });
CompilerParams.GenerateInMemory = true;
CompilerParams.GenerateExecutable = false;
CSharpCodeProvider Compiler = new CSharpCodeProvider();
CompilerResults Results = Compiler.CompileAssemblyFromDom(CompilerParams, codeUnit);
if (Results.Errors != null && Results.Errors.Count == 0)
{
CompiledAssembly = Results.CompiledAssembly;
}
return CompiledAssembly;
}
private CodeTypeDeclaration GetFields(CodeTypeDeclaration CodeType)
{
CodeType.Members.AddRange(GetGeneratedFieldCollection());
return CodeType;
}
private CodeTypeMember[] GetGeneratedFieldCollection()
{
var codeMemberFieldList = new List<CodeMemberField>();
foreach (var property in JsonSchema.Properties)
{
codeMemberFieldList.Add(new CodeMemberField
{
Type = new CodeTypeReference(JSchemaTypeHelper.GetJSchemaSystemType(property.Value.Type)),
Name = property.Key,
Attributes = MemberAttributes.Public
});
}
return codeMemberFieldList.ToArray();
}
private string[] GetReferenceList()
{
List<string> references = new List<string>();
references.AddRange(new string[] { "System", "System.Collections", "System.Collections.Generic" });
return references.ToArray();
}
}
答案 0 :(得分:0)
所以我最终搞清楚了,我必须先生成子类,然后使用生成的子类的类型创建一个List。此实现将允许您创建原始类型,对象和列表的字段。
public Assembly CreateType(JSchema schema)
{
CodeTypeDeclaration CodeType = new CodeTypeDeclaration();
CodeType.Name = schema.Id.ToString();
CodeType.IsClass = true;
CodeType.Attributes = MemberAttributes.Public;
CodeNamespace.Types.Add(CodeType);
CodeType = GetFields(CodeType, schema);
CodeCompileUnit CodeUnit = new CodeCompileUnit();
CodeUnit.ReferencedAssemblies.AddRange(GetReferenceList());
CodeUnit.Namespaces.Add(CodeNamespace);
return CreateTypeInMemory(CodeUnit);
}
private Assembly CreateTypeInMemory(CodeCompileUnit codeUnit)
{
Assembly CompiledAssembly = null;
CompilerParameters CompilerParams = new CompilerParameters();
CompilerParams.ReferencedAssemblies.AddRange(new[] { "System.dll" });
CompilerParams.GenerateInMemory = true;
CompilerParams.GenerateExecutable = false;
CSharpCodeProvider Compiler = new CSharpCodeProvider();
CompilerResults Results = Compiler.CompileAssemblyFromDom(CompilerParams, codeUnit);
if (Results.Errors != null && Results.Errors.Count == 0)
{
CompiledAssembly = Results.CompiledAssembly;
}
return CompiledAssembly;
}
private CodeTypeDeclaration GetFields(CodeTypeDeclaration CodeType, JSchema schema)
{
CodeType.Members.AddRange(GetGeneratedFieldCollection(schema));
return CodeType;
}
private CodeTypeMember[] GetGeneratedFieldCollection(JSchema schema)
{
var codeMemberFieldList = new List<CodeMemberField>();
foreach (var property in schema.Properties)
{
if (property.Value.Type.ToString() != "Array, Null" && property.Value.Type.ToString() != "Object, Null")
{
codeMemberFieldList.Add(new CodeMemberField
{
Type = new CodeTypeReference(JSchemaTypeHelper.GetJSchemaSystemType(property.Value.Type)),
Name = property.Key,
Attributes = MemberAttributes.Public
});
}
else if(property.Value.Type.ToString() == "Array, Null")
{
var generatedAssembly = CreateType(property.Value.Items.FirstOrDefault());
var type = GetTypeFromAssembly(generatedAssembly, property);
Type listType = typeof(List<>).MakeGenericType(type);
var codeMemberField = new CodeMemberField
{
Type = new CodeTypeReference(listType),
Name = property.Key,
Attributes = MemberAttributes.Public
};
codeMemberFieldList.Add(codeMemberField);
}
else
{
var generatedAssembly = CreateType(property.Value.Items.FirstOrDefault());
var type = GetTypeFromAssembly(generatedAssembly, property);
var codeMemberField = new CodeMemberField
{
Type = new CodeTypeReference(type),
Name = property.Key,
Attributes = MemberAttributes.Public
};
codeMemberFieldList.Add(codeMemberField);
}
}
return codeMemberFieldList.ToArray();
}
private string[] GetReferenceList()
{
List<string> references = new List<string>();
references.AddRange(new string[] { "System", "System.Collections", "System.Collections.Generic" });
return references.ToArray();
}
private Type GetTypeFromAssembly(Assembly generatedAssembly, KeyValuePair<string, JSchema> property)
{
string definedTypeName = property.Value.Items.FirstOrDefault().Id.ToString();
return generatedAssembly.DefinedTypes
.FirstOrDefault(definedtype => definedtype.Name == definedTypeName);
}