2012-12-06 85 views
0

我想知道是否可以創建一個方法,通過反射來更新屬性/字段,只需傳入要設置的屬性/字段的名稱即如何通過引用的字段/屬性訪問屬性

IFTDGN.Set("S009", "E1001", "B");

哪裏S009是包含在IFTDGN類中的一個字段,並E1001是一個字段/屬性通過S009現場訪問,最後B是我希望投入E1001屬性/字段的值。

我有這樣的代碼(可以很容易複製):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace EDIDemo 
{ 
    using System.Reflection; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      IFTDGN iftdgn = new IFTDGN(); 
      iftdgn.S009.E1001.Set("A"); 
      iftdgn.S009.E1002.Set("CC"); 

      iftdgn.Set("S009", "E1001", "B"); 

      Console.WriteLine(iftdgn.CreateMessage()); 
      Console.ReadKey(); 
     } 
    } 

    /// <summary> 
    /// Represents an International Forwarding and Transport Dangerous Goods Notification message 
    /// </summary> 
    class IFTDGN : EDIMessage 
    { 
     public S009 S009 = new S009(); 

     public IFTDGN() 
      : base() 
     { 
      base.RegisterMessage(this.GetType().Name); 
     } 

     public override string CreateMessage() 
     { 
      StringBuilder sb = new StringBuilder(); 

      sb.AppendLine("S009"); 
      sb.AppendFormat("\t{0} {1}\n", "E1001", S009.E1001.Code.Tag); 
      sb.AppendFormat("\t{0} {1}\n", "E1002", S009.E1002.Code.Tag); 

      return sb.ToString(); 
     } 

     public override void Set(string segment, string element, string code) 
     { 
      // *** THIS IS THE BIT I AM HAVING TROUBLE WITH ** 
      var fi_seg = this.GetType().GetFields().FirstOrDefault(p => p.Name == segment); 
      var pi_elem = fi_seg.GetType().GetProperties().FirstOrDefault(p => p.Name == element); 
     } 

    } 

    class S009 
    { 
     protected IDictionary<String, EDIDataElement> Elements = new Dictionary<String, EDIDataElement>() 
     { 
      { "E1001", new E1001() }, 
      { "E1002", new E1002() } 
     }; 

     public E1001 E1001 { get { return (E1001)Elements[ "E1001" ]; } } 
     public E1002 E1002 { get { return (E1002)Elements[ "E1002" ]; } } 
    } 

    abstract class EDIMessage 
    { 
     protected String MessageID; 

     protected EDIMessage() 
     { } 

     protected void RegisterMessage(String messageID) 
     { 
      this.MessageID = messageID; 
     } 

     public virtual void Set(String segment, String element, String code) 
     { 
      throw new NotImplementedException(); 
     } 

     public abstract String CreateMessage(); 

    } 

    abstract class EDIDataElement 
    { 
     public Code Code { get; private set; } 

     public virtual bool Mandatory 
     { 
      get 
      { 
       return false; 
      } 
     } 

     protected IList<Code> Codes = new List<Code>(); 
     protected String ElementID; 

     public virtual void Set(String code) 
     { 
      if (!Codes.Any(c => c.Tag == code)) 
       throw new Exception("Code '" + code + "' not found for element '" + ElementID + "'"); 

      this.Code = Codes.FirstOrDefault(c => c.Tag == code); 
     } 

     protected void RegisterElement(String elementID) 
     { 
      this.ElementID = elementID; 
     } 

    } 

    class E1001 : EDIDataElement 
    { 
     public E1001() 
      : base() 
     { 
      base.Codes.Add(new Code("A", "Code A")); 
      base.Codes.Add(new Code("B", "Code B")); 
      base.Codes.Add(new Code("C", "Code C")); 
      base.Codes.Add(new Code("D", "Code D")); 
      base.Codes.Add(new Code("E", "Code E")); 

      base.RegisterElement(this.GetType().Name); 
     } 

     public override void Set(String code) 
     { 
      base.Set(code); 
     } 

     public override bool Mandatory 
     { 
      get 
      { 
       return true; 
      } 
     } 

    } 

    class E1002 : EDIDataElement 
    { 
     public E1002() 
      : base() 
     { 
      base.Codes.Add(new Code("AA", "Code AA")); 
      base.Codes.Add(new Code("BB", "Code BB")); 
      base.Codes.Add(new Code("CC", "Code CC")); 
      base.Codes.Add(new Code("DD", "Code DD")); 
      base.Codes.Add(new Code("EE", "Code EE")); 

      base.RegisterElement(this.GetType().Name); 

     } 

     public override void Set(String code) 
     { 
      base.Set(code); 
     } 

     public override bool Mandatory 
     { 
      get 
      { 
       return true; 
      } 
     } 

    } 

    class Code 
    { 
     public string Tag { get; protected set; } 
     public string Name { get; protected set; } 

     public Code(string tag, string name) 
     { 
      Tag = tag; 
      Name = name; 
     } 
    } 

} 

基本上,我想pi_elem變量包含了E1001引用的屬性/字段的PropertyInfoFieldInfo,但它總是返回null

+0

可能重複[如何設置通過反射對象屬性(http://stackoverflow.com/questions/5370641/how-to -set-object-property-through-reflection) –

+0

這是在原始類中尋找屬性。我正在尋找訪問另一個級別的屬性和字段。 – Intrepid

+0

它仍然是同樣的事情,除了你第一次獲得第一個類型的屬性,然後對結果對象進行設置。 – poke

回答

1

我猜

var pi_elem = fi_seg.GetType().GetProperties().FirstOrDefault(p => p.Name == element); 

可能是:

var pi_elem = fi_seg.FieldType.GetProperties().FirstOrDefault(p => p.Name == element); 
+0

哇,有用!我只需要添加一個屬性集,以便我可以爲其寫入值。非常感謝jbl + 1 – Intrepid