2011-01-13 72 views
1

我只是在玩屬性,其中包含有關特定數據庫字段的一些信息。我已經創建了FieldAttribute類,它具有默認信息,如名稱,類型等。反射,屬性和屬性 - 學習ORM體系結構

我的問題是:是否可以創建一個方法來檢索此信息並嵌入到屬性中?我想我可以用代碼更好地溝通:

[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; } 
} 

我想在這裏做的是建立一個通用的GetMethod,使用字段屬性值從數據庫/ _underlyingObject獲取數據,只是「填寫的」 EG:

當我調用Foo.FooName時,getter將檢查屬性,並將getter名稱傳遞給GetFieldAttribute方法。

我該如何做到這一點?

這個想法是,當有一個小框架,這將成爲一個簡單的「ESRI數據庫提供者」的數據。

我真的很抱歉,我無法正確解釋這一點。

感謝您的幫助。

G.

+0

感覺這需要說:我希望這是你自己的好奇心,而不是在生產系統中使用。 – 2011-01-13 21:28:05

回答

2

除非你打算通過一些數據存儲庫檢索方法實例您的Foo對象,這需要動態編譯必要的注入你的getter和setter方法。

我反而建議你看看這樣

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

模式的getObject方法簽名會

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

在GetObject方法,你會體現在類型發現其所有字段屬性並將它們映射到實際的數據庫調用。這是非常簡單和常用的方法,可以這樣

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); 
     } 
    } 
} 
與列表OG

現在可以實現屬性,你可以構造一個SQL字符串這樣

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 

有了結果,你可以實例化一個Foo -instance,填寫其屬性,並返回實例

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