【问题标题】:How to access properties through a referenced field/property如何通过引用的字段/属性访问属性
【发布时间】:2012-12-06 14:03:28
【问题描述】:

我想知道是否可以创建一个方法,通过反射来更新属性/字段,只需传入要设置的属性/字段的名称,即

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

其中S009 是包含在IFTDGN 类中的字段,E1001 是通过S009 字段访问的字段/属性,最后B 是我要放入@ 的值987654328@属性/字段。

我有这段代码(以便于重现):

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

【问题讨论】:

  • 那是在原始类中寻找属性。我正在考虑访问另一个级别的属性和字段。
  • 还是一样的,只是先获取第一种类型的属性,然后再对生成的对象进行设置。
  • @poke: 如果fi_seg 给了我S009 字段的FieldInfo 对象,那么'pi_elem' 在尝试获取封闭的'E1001' 的PropertyInfo 时如何返回null财产?
  • 我猜 fi_seg 是 FieldInfo 类型,它没有任何“E1001”属性。你应该看看目标类型。

标签: c# reflection


【解决方案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 );

【讨论】:

  • 哇,好用!我只需要添加一个属性集,这样我就可以向它写入值。非常感谢 jbl +1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-03
  • 1970-01-01
  • 2023-03-31
  • 2012-03-10
  • 1970-01-01
  • 2016-05-09
相关资源
最近更新 更多