2016-08-18 6 views
1

CodeDomを使用して複雑なオブジェクトを作成しようとしています。今、私は、次のような単純なオブジェクトの作成とまったく問題ありません: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

サブクラスの定義が不足していますか? – SzymonK

+0

コードを表示してください。 –

+0

@BradleyUffnerが私の現在の実装を追加しました。 – R007

答えて

0

は、だから私はそれを考え出すことになった、私は最初のサブクラスを生成し、生成されたサブクラスの型を使用してリストを作成する必要がありました。この実装では、プリミティブ型、オブジェクト、およびリストであるフィールドを作成できます。

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); 
    } 
関連する問題