2011-01-13 75 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