2010-09-28 251 views
1

基本上我只想从基类中通过[Test]属性获取派生类的属性。C#反射:如何从基类中获得派生类的属性

这里是我的示例代码:

namespace TestConsole 
{ 
    public class BaseClass 
    { 
     private System.Int64 _id; 

     public BaseClass() 
     { } 

     [Test] 
     public System.Int64 ID 
     { 
      get { return _id;} 
      set { _id = value;} 
     } 

     public System.Xml.XmlNode ToXML() 
     { 
      System.Xml.XmlNode xml = null; 

      //Process XML here 

      return xml; 
     } 
    } 

    public class DerivedClass : BaseClass 
    { 
     System.String _name; 

     public DerivedClass() 
     { } 

     [Test] 
     public System.String Name 
     { 
      get { return _name; } 
      set { _name = value; } 
     } 
    } 

    public class TestConsole 
    { 
     public static void main() 
     { 
      DerivedClass derivedClass = new DerivedClass(); 

      System.Xml.XmlNode xmlNode = derivedClass.ToXML(); 
     } 
    } 
} 

我想要的xmlNode是这样的:

<root> 
    <class name="DerivedClass"> 
    <Field name="Id"> 
    <Field name="Name"> 
    </class> 
</root> 

谢谢

+1

它看起来像你想推倒重来......你有没有尝试[XML序列化](http://msdn.microsoft.com/en-us/library/ms950721.aspx)? – 2010-09-28 18:19:40

+1

“从基类获取派生类的属性”并不意味着什么。只能在派生类的类型上调用GetProperties。 – 2010-09-28 18:21:44

回答

8

您可以在每个PropertyInfo打电话this.GetType().GetProperties()和呼叫GetCustomAttributes()找到具有该属性的属性。

您需要递归运行循环来扫描基本类型的属性。

2

我不认为XmlNode是一个很好的类用于此目的。 首先,创建一个XmlNode需要你传递一个XmlDocument,这不是一个漂亮的解决方案。其次,使用LINQ可以很好地提取属性和属性值,我认为这可能与LINQ to XML(特别是,XElement类)很好地集成在一起。

我写了一些代码,做的:

using System; 
using System.Linq; 
using System.Xml.Linq; 

[AttributeUsage(AttributeTargets.Property)] 
class PropertyAttribute : Attribute { } 

class BaseClass 
{ 
    [Property] 
    public int Id { get; set; } 

    IEnumerable<XElement> PropertyValues { 
     get { 
      return from prop in GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public) 
        where prop.GetGetMethod() != null 
        let attr = prop.GetCustomAttributes(typeof(PropertyAttribute), false) 
            .OfType<PropertyAttribute>() 
            .SingleOrDefault() 

        where attr != null 
        let value = Convert.ToString (prop.GetValue(this, null)) 

        select new XElement ("field", 
         new XAttribute ("name", prop.Name), 
         new XAttribute ("value", value ?? "null") 
        ); 
     } 
    } 

    public XElement ToXml() 
    { 
     return new XElement ("class", 
       new XAttribute ("name", GetType().Name), 
       PropertyValues 
       ); 
    } 
} 

class DerivedClass : BaseClass 
{ 
    [Property] 
    public string Name { get; set; } 
} 

public static class Program 
{ 
    public static void Main() 
    { 
     var instance = new DerivedClass { Id = 42, Name = "Johnny" }; 
     Console.WriteLine (instance.ToXml()); 
    } 
} 

此输出下面的XML到控制台:

<class name="DerivedClass"> 
    <field name="Name" value="Johnny" /> 
    <field name="Id" value="42" /> 
</class> 
+0

哦,我只是注意到你不需要那里的价值。您需要在那里删除值检索部分。但是我仍然认为这个代码示例是有用的。 – 2010-09-28 19:02:33

+1

你的代码是完美的。我只想注意到“BindingFlags.Instance”是从基类获取属性的诀窍。 – Nathan 2012-03-07 15:10:21