2017-12-30 57 views
0

クラスビルダークラスを作成します。それは適切に動作し、私のクラスは必要なデータに基づいて作成されます。しかし、私はクラスに追加されたプロパティを見ることができませんでした。C#:私のクラス(動的に作成された)クラスが表示されない理由

それは私のクラスのビルダークラスです:

using System; 
using System.Reflection; 
using System.Reflection.Emit; 

namespace aitClassBuilder 
{ 
    public interface IclassBuilder 
    { 
     float Read(Int32 first, Int32 second); 
     string Write(); 
    } 
    public class ClassBuilder : IclassBuilder 
    { 
     AssemblyName asemblyName; 
     public ClassBuilder(string ClassName, string ClassId) 
     { 
      this.asemblyName = new AssemblyName(ClassName); 
     } 
     public object CreateObject() 
     { 
      TypeBuilder DynamicClass = this.CreateClass(); 
      this.CreateConstructor(DynamicClass); 


     CreateProperty(DynamicClass, "ColumnId", Type.GetType("System.Int32")); 
     CreateProperty(DynamicClass, "ColumnName", Type.GetType("System.String")); 

      Type type = DynamicClass.CreateType(); 
      return Activator.CreateInstance(type); 
     } 
     private TypeBuilder CreateClass() 
     { 
      AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(this.asemblyName, AssemblyBuilderAccess.Run); 
      ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule"); 
      TypeBuilder typeBuilder = moduleBuilder.DefineType(this.asemblyName.FullName, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout, null); 
      return typeBuilder; 
     } 
     private void CreateConstructor(TypeBuilder typeBuilder) 
     { 
      typeBuilder.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); 
     } 
     private void CreateProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType) 
     { 
      FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private); 
      PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null); 
      MethodBuilder getPropMthdBldr = typeBuilder.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes); 
      ILGenerator getIl = getPropMthdBldr.GetILGenerator(); 
      getIl.Emit(OpCodes.Ldarg_0); 
      getIl.Emit(OpCodes.Ldfld, fieldBuilder); 
      getIl.Emit(OpCodes.Ret); 
      MethodBuilder setPropMthdBldr = typeBuilder.DefineMethod("set_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new[] { propertyType }); 
      ILGenerator setIl = setPropMthdBldr.GetILGenerator(); 
      Label modifyProperty = setIl.DefineLabel(); 
      Label exitSet = setIl.DefineLabel(); 
      setIl.MarkLabel(modifyProperty); 
      setIl.Emit(OpCodes.Ldarg_0); 
      setIl.Emit(OpCodes.Ldarg_1); 
      setIl.Emit(OpCodes.Stfld, fieldBuilder); 
      setIl.Emit(OpCodes.Nop); 
      setIl.MarkLabel(exitSet); 
      setIl.Emit(OpCodes.Ret); 
      propertyBuilder.SetGetMethod(getPropMthdBldr); 
      propertyBuilder.SetSetMethod(setPropMthdBldr); 
     } 
     public float Read(Int32 first, Int32 second) 
     { 
      return first + second; 
     } 
     public string Write() 
     { 
      string result = ""; 
      return result; 
     } 
    } 
} 

と私はこのようなクラスから使用してください。私は私のクラスのColumnIDのプロパティへのアクセスを取得したい場合は、このコードの末尾に

 aitClassBuilder.ClassBuilder myCls = 
         new ClassBuilder("Sys_Columns", "1003"); 
     object myTbl = myCls.CreateObject(); 
     MessageBox.Show(myTbl.ColumnID); 

エラーが発生しました。しかし、クラスをウォッチウィンドウに追加すると、クラスにプロパティが追加されていることがわかりました。どうしてか分かりません? お願いします。

エラーの詳細は: エラー 'オブジェクト'に 'ColumnID'の定義が含まれておらず、 'オブジェクト'のタイプの最初の引数を受け入れる拡張メソッド 'ColumnID'が見つかりませんでした(usingディレクティブFormSample E:¥New Hafiz¥aitClassBuilder¥FormSample¥Form1.cs 29 Active

+2

例外は.. –

+0

おそらく約10行以下のコードでこの質問をしていた可能性があります –

+0

エラーメッセージを追加しませんでした。これは常に厄介なものです –

答えて

0

何が起こっていますか? 030。

もう1つ別のDictionary<string, object>を作成するのではなく、その場で新しいクラスを生成するのはなぜですか?あなたが強いタイプ(私はあなたがそうでなければC#が必要な理由?)に固執することを好む場合には、拡張メソッドTResult TryGetValue<TResult>(this Dictionary<string, object> @this, string key)が宣言されるかもしれません。

あなたが示したコードの95%が消えて、あなたが始めた問題は...消えてしまいます。

+1

こんにちは、ありがとうございました。このソリューションは完璧で素晴らしい機能を備えています。あなたが言ったように、コードの95%は消えなければなりません。ありがとうございました。 – Farzin

+0

@Farzinあなたは自分のOSをまだ始まっていないので、幸いなことです。 –

0

オブジェクトを(Sys_Columns)にキャストする必要があります。エラーメッセージとして

Sys_Columns myTbl = (Sys_Columns)myCls.CreateObject(); 
+0

実際に私はデザインモードでSys_Columnsクラスを持っていません。私はこれを試すが、このエラーが表示されます:型または名前空間の名前 'Sys_Columns'が見つかりませんでした – Farzin

+0

どこにbaseDataが定義されていますか? – rokkerboci

+0

申し訳ありませんがコードを変更します。私の物件のリストです。私は2つの特定のプロパティに置き換えます。 – Farzin

2

objectタイプがColumnIDと呼ばれるプロパティを持っていません示しています。オブジェクトを実際のタイプにキャストできないため、ここでdynamicキーワードを使用する必要があります。したがって、コードは次のようになります。

dynamic myTbl = myCls.CreateObject(); 
MessageBox.Show(myTbl.ColumnID); 

この方法では、プロパティの種類についてコンパイル時のチェックは行われません。

+0

そして、あなたのC#全体が 'ダイナミック'になり、Visual Studioで奇妙な 'Java - # - Script'コードをコーディングしているのが分かります。 –

+1

これは、OPの要件で既に起こったことです。 – abto

+0

「動的な」地獄を避ける唯一の可能性は、ソースコードで書かれたインターフェースを動的に作成されたクラスに導入し、そのインターフェースにキャストすることです。 – abto

関連する問題