2011-01-13 6 views
1

私は、特定のデータベースフィールドに関する情報を含む属性で再生しています。私は既にFieldAttributeクラスを作成しました。名前、型などのデフォルトの情報を持っています。リフレクト、プロパティ、および属性 - ORMアーキテクチャの学習

私の質問は、この情報を取得してプロパティに組み込む単一のメソッドを作成できますか? 「記入」だけのフィールドは、データベース/ _underlyingObjectからデータをフェッチする属性値を使用していることを、一般的なGetMethodを構築することです私はここで何をしたいのか

[AttributeUsage(AttributeTargets.Property,AllowMultiple=false,Inherited=true)] 
public class FieldAttribute:Attribute 
{ 
    protected string _FieldName; 
    protected esriFieldType _FieldType; 
    protected bool _NotNullable; 
    protected bool _IsPrimary; 
    protected bool _IsForeign; 
    protected int _Index; 

    public virtual string FieldName 
    { 
     get { return this._FieldName; } 
     set { this._FieldName = value; } 
    } 

    public virtual esriFieldType FieldType 
    { 
     get { return this._FieldType; } 
     set { this._FieldType = value; } 
    } 

    public virtual bool NotNullable 
    { 
     get { return this._NotNullable; } 
     set { this._NotNullable = value; } 
    } 

    public virtual int Index 
    { 
     get { return this._Index; } 
     set { this._Index = value; } 
    } 

    public FieldAttribute(string fieldName, esriFieldType fieldType,int position) 
    { 
     this.FieldName = fieldName; 
     this.FieldType = fieldType; 
     _IsPrimary = false; 
     _IsForeign = false; 
     Index = position; 
    } 
} 

// my main abstract class 
public abstract class ObjectWrapper:IObjectWrapper 
{ 
    protected int _ObjectId; 
    protected IObject _UnderlyingObject; 

    public virtual IObject UnderlyingObject 
    { 
     get { return this._UnderlyingObject; } 
    } 

    public virtual int ObjectId 
    { 
     get { return this._ObjectId; } 
    } 

    public virtual void Store() 
    { 
     try 
     { 
      _UnderlyingObject.Store(); 
     } 
     catch (COMException comEx) 
     { 
      // log com exception 
     } 
     catch (Exception ex) 
     { 
      // log 
     } 
    } 

    // this method retrieves field information 
    private FieldAttribute GetFieldAttribute(string propertyName) 
    { 
     FieldAttribute propertyAttribute = null; 

     try 
     { 
      PropertyInfo propInfo = this.GetType().GetProperty(propertyName); 
      object[] attributes = propInfo.GetCustomAttributes(typeof(FieldAttribute), true); 
      if (attributes.Length == 1) 
       propertyAttribute = (FieldAttribute)attributes[0]; 
     } 
     catch (AmbiguousMatchException ambEx) 
     { 
      // log 
     } 
     catch (ArgumentException argEx) 
     { 
      // log 
     } 

     return propertyAttribute; 
    } 
} 

// my concrete class 
public class Foo:ObjectWrapper 
{   
    [Field("FOO_NAME",esriFieldType.esriFieldTypeString,1); 
    public string FooName { get; set; } 

    [Field("FOO_AGE",esriFieldType.esriFieldTypeInteger,2); 
    public int FooAge { get; set; } 
} 

と:私は、コードとのより良い通信することができると思いますgetterとsetter for me.EG:

私がFoo.FooNameを呼び出すと、getterはGetFieldAttributeメソッドにゲッター名を渡して属性をチェックします。

どうすればこの問題を解決できますか?

小さなフレームワークがある場合、これはデータのための簡単な「ESRIデータベースプロバイダ」になります。

私はこれを正しく説明できないことを本当に残念です。

ありがとうございました。

G.

+0

これはあなた自身の好奇心のためであり、本番システムでは使用しないことを望みます。 –

+0

@qstarin:プロダクションで使用しない理由は何ですか?アイデアは悪いですか?私はこれがすぐに生産に使われると言っているわけではありませんが、すべてのプロジェクトはどこかで始まらなければなりません。ご協力ありがとうございました。 –

+0

あなた自身のものを開発するよりも、既存のORMソリューションを習得して使用することは、はるかに生産的になります。それがあなた自身の学習のためのものなら、価値があります。これが仕事に払われれば、それは怠慢で無責任なようです(それは少し強いですが、それほど遠くはありません)。独自のORMを書くアイデアは反パターンです。 –

答えて

2

あなたには、いくつかのデータリポジトリ検索方法を通して、あなたのFooオブジェクトをインスタンス化を計画している場合を除き、これはあなたのゲッターとセッターに必要を注入する動的コンパイルが必要となります。

私の代わりにGetObjectメソッドのメソッドシグネチャは、あなたがそのすべてを見つけるタイプの上に反映されますGetObjectメソッドで

public static T GetObject<T>(object id) where T: new() 

だろうこの

var foo = DataRepository.GetObject<Foo>(some_id); 

のようにパターンを見て、あなたをお勧めしますフィールド属性を作成し、実際のデータベース呼び出しにマッピングします。これは非常に単純かつ一般的なアプローチであり、あなたはその結果、あなたがfooのインスタンスを作成することができますしてこの

var columns = GetFieldAttributes<T>().Select(t => t.Item2.FieldName); 
var sql = "SELECT "+ String.Join("," columns) +" FROM table WHERE id = "+ id; 

var result = ... execute the query and return ie a datareader 

ようなSQL文字列を構築することができる属性のリストOGと今、この

public static IEnumerable<Tuple<PropertyInfo, FieldAttribute>> GetFieldAttributes<T>() 
{ 
    var properties = typeof(T).GetProperties(); 
    foreach (var prop in properties) 
    { 
     var attribute = prop.GetCustomAttributes(typeof(FieldAttribute), true).FirstOrDefault(); 
     if (attribute != null) 
     { 
      yield return new Tuple<PropertyInfo, FieldAttribute>(prop, attribute); 
     } 
    } 
} 

のように達成することができますインスタンスのプロパティを記入し、インスタンスを返す

var instance = new T(); 

result.Read() 
var dictionary = new Dictionary<string, object>(); 

// get the columns returned from database 
for (int i = 0; i < reader.FieldCount; i++) 
{ 
    string fieldName = reader.GetName(i); 
    object value = reader.GetValue(i); 

    dictionary.Add(fieldName, value); 
} 

// bind the columns from database to the properties of our object 
foreach (var c in columns) 
{ 
    var attr = c.Item2; 
    var value = dictionary[attr.FieldName]; 

    if (value is DBNull) 
    { 
     value = null; 
    } 

    typeof(T).InvokeMember(c.Item1.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.Instance, null, instance, new[] { value }); 
} 

// return the new object with all its values filled out 
return instance 
関連する問題