2017-04-19 89 views
1

如何訪問父對象或所有者對象的自定義屬性。 看看SQLFieldInfo的FieldInfo屬性結構C#訪問所有者對象的自定義屬性

下面是一個更詳細的程序,將編譯和運行,顯示我需要什麼。

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 

     Employee myclass = new Employee(); 

     // Load from sql server... 
     myclass.Name = "Alain"; 
     myclass.Age = 51; 
     //---- 

     MessageBox.Show(myclass.Name.ToString()); // Should return Alain 
     MessageBox.Show(myclass.Age.FieldInfo.Type.ToString()); // Should output "int" 
    } 
} 

// This next class is generated by a helper exe that reads SQL table design and create the class from it 
[SQLTableAttribute(DatabaseName = "Employees", Schema = "dbo", TableName = "Employees")] 
public class Employee 
{ 
    [SQLFieldAttribute(FieldName = "ID", Type = SqlDbType.Int)] 
    public SQLFieldInfo<int> ID { get; set; } 

    [SQLFieldAttribute(FieldName = "Name", Type = SqlDbType.NVarChar, Size = 200)] 
    public SQLFieldInfo<String> Name { get; set; } 

    [SQLFieldAttribute(FieldName = "Age", Type = SqlDbType.Int)] 
    public SQLFieldInfo<int> Age { get; set; } 
} 


public struct SQLFieldInfo<T> 
{ 

    private readonly T value; 

    public SQLFieldInfo(T Value) 
    { 
     this.value = Value; 
    } 


    public static implicit operator SQLFieldInfo<T>(T Value) 
    { 
     return new SQLFieldInfo<T>(Value); 
    } 


    public T Value 
    { 
     get 
     { 
      return this.value; 
     } 
    } 


    public override string ToString() 
    { 
     return this.value.ToString(); 
    } 


    public SQLFieldAttribute FieldInfo 
    { 
     get 
     { 
      // Need to retreive the attribute class of the parent or declaring member 

      return null; 
     } 
    } 
} 

// Holds the sql field information 
public class SQLFieldAttribute : Attribute 
{ 
    public string FieldName { get; set; } 
    public SqlDbType Type { get; set; } 
    public bool AllowNull { get; set; } 
    public int Size { get; set; } 
} 

// Holds the sql table information 
public class SQLTableAttribute : Attribute 
{ 
    public string DatabaseName { get; set; } 
    public string Schema { get; set; } = "dbo"; 
    public string TableName { get; set; } 
} 

謝謝!

阿蘭

+0

B應該怎麼知道它嵌入'A'內部?我猜你可以檢查'B.myprop2'內的調用堆棧以查看「A.myprop」是否是前一幀。然而,依賴於調用堆棧的佈局正在尋求麻煩。特別是它可能在發佈版本中有不同的佈局。 –

+0

我不希望B知道它,但從CLR是的,我想用反射系統會知道創建者實例,並從那裏訪問自定義屬性應該很容易。 – user1603581

回答

1

首先,MSDN是你的朋友。

然後,如果你想獲得對祖先的屬性只是在方法的繼承標誌指定true

var attribute = typeof(A).GetProperty("myprop").GetCustomAttributes(true) 
         .OfType<MycustomAttrib>().FirstOrDefault(); 
+0

謝謝Arsen,但如果你不知道調用者類和道具名稱,B類是一個泛型類,並且可能在任何地方聲明。 – user1603581

+0

你對A的瞭解嗎?它是作爲泛型參數傳遞給B的類型嗎? –

+0

在這一點上,我對A一無所知,我需要的是基於類X的類B的成員的自定義屬性(如果存在)。 – user1603581

1

我的數據類如下(應該是相當平移,以上述A) :

public class Foo 
{ 
    [Argument(Help = "Name", AssignmentDelimiter = "=")] 
    public string Name 
    { 
     get; 
     set; 
    } 
} 

甲助手類負責讀取對象的屬性值:

static public string GetCommandLineDelimiter<T>(Expression<Func<T>> property) 
{ 
    if(property != null) 
    { 
     var memberExpression = (MemberExpression)property.Body; 
     string propertyName = memberExpression.Member.Name; 
     PropertyInfo prop = typeof(Arguments).GetProperty(propertyName); 
     if(prop != null) 
     { 
      object[] dbFieldAtts = prop.GetCustomAttributes(typeof(ArgumentAttribute), true); 
      if(dbFieldAtts.Length > 0) 
      { 
       return ((ArgumentAttribute)dbFieldAtts[0]).AssignmentDelimiter; 
      } 
     } 
    } 
    return null; 
} 

要使用它,簡單地說:

string delimiter = GetCommandLineDelimiter(() => myObject.Name); 

這將讓AssignmentDelimiter的財產名稱,即 「=」 的屬性值。

0

This Works。我正在做一個惰性的自定義屬性的引用的初始化,通過使用反射來查看的所有屬性的所有類型

public class MycustomAttribAttribute : Attribute 
{ 
    public MycustomAttribAttribute(string name) 
    { 
     this.Name=name; 
    } 
    public string Name { get; private set; } 
} 
class A 
{ 
    public A() { MyProp=new B(); } 
    [MycustomAttrib(name: "OK")] 
    public B MyProp { get; set; } 
} 


class B 
{ 
    private static Lazy<MycustomAttribAttribute> att = new Lazy<MycustomAttribAttribute>(() => 
    { 
     var types = System.Reflection.Assembly.GetExecutingAssembly().DefinedTypes; 

     foreach(var item in types) 
     { 
      foreach(var prop in item.DeclaredProperties) 
      { 
       var attr = prop.GetCustomAttributes(typeof(MycustomAttribAttribute), false); 
       if(attr.Length>0) 
       { 
        return attr[0] as MycustomAttribAttribute; 
       } 
      } 
     } 
     return null; 
    }); 
    public string MyProp2 
    { 
     get 
     { 
      return att.Value.Name; 
     } 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     // Finds the attribute reference and returns "OK" 
     string name = (new A()).MyProp.MyProp2; 
     // Uses the stored attribute reference to return "OK" 
     string name2 = (new A()).MyProp.MyProp2; 
    } 
} 
+0

謝謝ja72,如果添加到類中第二個屬性MyProp2,您編寫的代碼總是返回第一個聲明屬性的自定義屬性。真正的問題是,我們真的需要知道來電者的道具。公共A(){MyProp = new B(); } [MycustomAttrib(name:「OK」)] public B MyProp {get;組; } [MycustomAttrib(name:「OK2」)] public B MyProp2 {get;組; } } – user1603581

+0

用添加的信息編輯問題,以清楚地知道你究竟在問什麼。請提供_almost_編譯的最小可驗證示例。 – ja72

+0

我已更新我的問題JA72 :) – user1603581