2017-04-19 39 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