Get member value by its name

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jan Kucera

    Get member value by its name

    Hi,
    I have structure like this:
    namespace Namespace
    {
    public class User
    {
    public Subnamespace.Se ttings Settings = new Subnamespace.Se ttings();
    }
    namespace Subnamespace
    {
    public class Settings
    {
    public string MyValue { get { return "Hello from there"; } }
    }
    public static class Helper
    {
    public static User User = new User();
    }
    }
    }

    now, I would like to get the value from string
    "Namespace.Subn amespace.Helper .User.Settings. MyValue".

    Reinout Waelput gave me on MSDN forums this code:

    string Location = "MyNamespace.My Class.TheStruct .TheStruct2.MyV alue";
    string s = Location.Substr ing(0, Location.IndexO f("."));
    Location = Location.Substr ing(Location.In dexOf(".") + 1);
    while (Type.GetType(s ) == null)
    {
    s = string.Concat(s , ".", Location.Substr ing(0, Location.IndexO f(".")));
    Location = Location.Substr ing(Location.In dexOf(".") + 1);
    }
    System.Type pageType = Type.GetType(s) ;
    System.Reflecti on.FieldInfo myField;
    while (Location.Index Of(".") >= 1)
    {
    string str = Location.Substr ing(0, Location.IndexO f("."));
    Location = Location.Substr ing(Location.In dexOf(".") + 1);
    myField = pageType.GetFie ld(str);
    pageType = myField.GetValu e(pageType).Get Type();
    }
    pageType.GetFie ld(Location, System.Reflecti on.BindingFlags .GetField);

    Which works well, however fails in my case, probably because of the
    Subnamespace.Se ttings declaration. The exception is:
    System.Argument Exception was unhandled
    Field 'Settings' defined on type 'Namespace.User ' is not a field on the
    target object which is of type 'System.Runtime Type'.
    at System.Reflecti on.RtFieldInfo. CheckConsistenc y(Object target)
    at System.Reflecti on.RtFieldInfo. InternalGetValu e(Object obj, Boolean
    doVisibilityChe ck, Boolean doCheckConsiste ncy)
    at System.Reflecti on.RtFieldInfo. GetValue(Object obj)

    VisualStudio during debug, when selecting
    Namespace.Subna mespace.Helper. User.Settings.M yValue have no troubles.

    Any idea how to handle the cross namespace declaration?

    Thanks a lot,
    Jan

  • John Duval

    #2
    Re: Get member value by its name

    Hi Jan,
    I was able to get the string "Hello from there" using this code:

    string inputString =
    "Namespace.Subn amespace.Helper .User.Settings. MyValue";
    int lastDot = inputString.Las tIndexOf('.');
    string typeName = inputString.Sub string(0, lastDot);
    string propertyName = inputString.Sub string(lastDot + 1);

    Namespace.User user = new Namespace.User( );
    Type userType = user.Settings.G etType();
    PropertyInfo pi = userType.GetPro perty(propertyN ame);
    object output = pi.GetValue(use r.Settings, null);

    There isn't really a problem with the embedded namespace that I saw.

    By the way, this code isn't very robust, since it assumes a lot about
    the input string. I'm not sure where you get your input string from,
    but it seems fragile to me to have to parse the string to separate the
    type from the property name. Perhaps the calling code already knows
    this information? If not, you'd probably want to add some error
    handling in case the property does not exist, or that kind of thing.

    Hope that helps,
    John

    Jan Kucera wrote:
    Hi,
    I have structure like this:
    namespace Namespace
    {
    public class User
    {
    public Subnamespace.Se ttings Settings = new Subnamespace.Se ttings();
    }
    namespace Subnamespace
    {
    public class Settings
    {
    public string MyValue { get { return "Hello from there"; } }
    }
    public static class Helper
    {
    public static User User = new User();
    }
    }
    }
    >
    now, I would like to get the value from string
    "Namespace.Subn amespace.Helper .User.Settings. MyValue".
    >
    Reinout Waelput gave me on MSDN forums this code:
    >
    string Location = "MyNamespace.My Class.TheStruct .TheStruct2.MyV alue";
    string s = Location.Substr ing(0, Location.IndexO f("."));
    Location = Location.Substr ing(Location.In dexOf(".") + 1);
    while (Type.GetType(s ) == null)
    {
    s = string.Concat(s , ".", Location.Substr ing(0, Location.IndexO f(".")));
    Location = Location.Substr ing(Location.In dexOf(".") + 1);
    }
    System.Type pageType = Type.GetType(s) ;
    System.Reflecti on.FieldInfo myField;
    while (Location.Index Of(".") >= 1)
    {
    string str = Location.Substr ing(0, Location.IndexO f("."));
    Location = Location.Substr ing(Location.In dexOf(".") + 1);
    myField = pageType.GetFie ld(str);
    pageType = myField.GetValu e(pageType).Get Type();
    }
    pageType.GetFie ld(Location, System.Reflecti on.BindingFlags .GetField);
    >
    Which works well, however fails in my case, probably because of the
    Subnamespace.Se ttings declaration. The exception is:
    System.Argument Exception was unhandled
    Field 'Settings' defined on type 'Namespace.User ' is not a field on the
    target object which is of type 'System.Runtime Type'.
    at System.Reflecti on.RtFieldInfo. CheckConsistenc y(Object target)
    at System.Reflecti on.RtFieldInfo. InternalGetValu e(Object obj, Boolean
    doVisibilityChe ck, Boolean doCheckConsiste ncy)
    at System.Reflecti on.RtFieldInfo. GetValue(Object obj)
    >
    VisualStudio during debug, when selecting
    Namespace.Subna mespace.Helper. User.Settings.M yValue have no troubles.
    >
    Any idea how to handle the cross namespace declaration?
    >
    Thanks a lot,
    Jan

    Comment

    • Mythran

      #3
      Re: Get member value by its name

      Please fix your date/clock. Or travel back to our time and let us know how
      you did it :) Posting in the future is frowned upon and really doesn't help
      you much here.

      Mythran

      Comment

      • Bruce Wood

        #4
        Re: Get member value by its name


        Jan Kucera wrote:
        Hi,
        I have structure like this:
        namespace Namespace
        {
        public class User
        {
        public Subnamespace.Se ttings Settings = new Subnamespace.Se ttings();
        }
        namespace Subnamespace
        {
        public class Settings
        {
        public string MyValue { get { return "Hello from there"; } }
        }
        public static class Helper
        {
        public static User User = new User();
        }
        }
        }
        >
        now, I would like to get the value from string
        "Namespace.Subn amespace.Helper .User.Settings. MyValue".
        >
        Reinout Waelput gave me on MSDN forums this code:
        >
        string Location = "MyNamespace.My Class.TheStruct .TheStruct2.MyV alue";
        string s = Location.Substr ing(0, Location.IndexO f("."));
        Location = Location.Substr ing(Location.In dexOf(".") + 1);
        while (Type.GetType(s ) == null)
        {
        s = string.Concat(s , ".", Location.Substr ing(0, Location.IndexO f(".")));
        Location = Location.Substr ing(Location.In dexOf(".") + 1);
        }
        System.Type pageType = Type.GetType(s) ;
        System.Reflecti on.FieldInfo myField;
        while (Location.Index Of(".") >= 1)
        {
        string str = Location.Substr ing(0, Location.IndexO f("."));
        Location = Location.Substr ing(Location.In dexOf(".") + 1);
        myField = pageType.GetFie ld(str);
        pageType = myField.GetValu e(pageType).Get Type();
        }
        pageType.GetFie ld(Location, System.Reflecti on.BindingFlags .GetField);
        >
        Which works well, however fails in my case, probably because of the
        Subnamespace.Se ttings declaration. The exception is:
        System.Argument Exception was unhandled
        Field 'Settings' defined on type 'Namespace.User ' is not a field on the
        target object which is of type 'System.Runtime Type'.
        at System.Reflecti on.RtFieldInfo. CheckConsistenc y(Object target)
        at System.Reflecti on.RtFieldInfo. InternalGetValu e(Object obj, Boolean
        doVisibilityChe ck, Boolean doCheckConsiste ncy)
        at System.Reflecti on.RtFieldInfo. GetValue(Object obj)
        >
        VisualStudio during debug, when selecting
        Namespace.Subna mespace.Helper. User.Settings.M yValue have no troubles.
        >
        Any idea how to handle the cross namespace declaration?
        >
        Thanks a lot,
        Jan
        I assume that you're getting the exception on the line that says:

        pageType = myField.GetValu e(pageType).Get Type();

        because the error is saying exactly what's wrong: pageType is an
        instance of System.Type, and System.Type has no field named "Settings".

        The problem is that you're trying to get the _value_ of the "Settings"
        field from a Namespace.User instance, but you're not supplying an
        instance. Since there is a different value for "Settings" in every
        Namespace.User object, how can you get a value if you don't specify
        from which instance you want the value? You can do that only if
        "Settings" is static (and therefore there's only one shared between all
        instances), but it's not.

        If you look at the other code posted on this thread, you'll see the
        line:

        Namespace.User newUser = new Namespace.User( );

        or something like that. That's the key. You have to create an instance
        in order to get the value of its "Settings" field.

        On the other hand, if all you want is the type of Settings, you should
        do that like this:

        ....
        myField = pageType.GetFie ld(str);
        pageType = myField.FieldTy pe;
        }
        pageType = pageType.GetFie ld(Location,
        System.Reflecti on.BindingFlags .GetField).Fiel dType;

        In otherwords, don't call the GetValue() method; use the FieldType
        property instead.

        Comment

        • Jan Kucera

          #5
          Re: Get member value by its name

          Mythran,
          Please accept my apologizies, if I wanted to post in future to gain your
          attention I would set it years forward. This wasn't intended and I've
          adjusted the date settings in my best belief :)
          Jan

          PS: And thanks for pointing that out, I wouldn't noticed it.


          "Mythran" <kip_potter@hot mail.comREMOVET RAILwrote in message
          news:u6qiMcQpGH A.4208@TK2MSFTN GP04.phx.gbl...
          Please fix your date/clock. Or travel back to our time and let us know
          how you did it :) Posting in the future is frowned upon and really
          doesn't help you much here.
          >
          Mythran
          >

          Comment

          • Jan Kucera

            #6
            Re: Get member value by its name

            Hi John,
            unfortunately you assume I know the members declarations at design time.
            This is not true, I have to completely search the runtime types to find out
            the value as well as the VisualStudio does when hovering over the selected
            string during debug.
            Jan

            "John Duval" <JohnMDuval@gma il.comwrote in message
            news:1152617005 .246204.232900@ h48g2000cwc.goo glegroups.com.. .
            Hi Jan,
            I was able to get the string "Hello from there" using this code:
            >
            string inputString =
            "Namespace.Subn amespace.Helper .User.Settings. MyValue";
            int lastDot = inputString.Las tIndexOf('.');
            string typeName = inputString.Sub string(0, lastDot);
            string propertyName = inputString.Sub string(lastDot + 1);
            >
            Namespace.User user = new Namespace.User( );
            Type userType = user.Settings.G etType();
            PropertyInfo pi = userType.GetPro perty(propertyN ame);
            object output = pi.GetValue(use r.Settings, null);
            >
            There isn't really a problem with the embedded namespace that I saw.
            >
            By the way, this code isn't very robust, since it assumes a lot about
            the input string. I'm not sure where you get your input string from,
            but it seems fragile to me to have to parse the string to separate the
            type from the property name. Perhaps the calling code already knows
            this information? If not, you'd probably want to add some error
            handling in case the property does not exist, or that kind of thing.
            >
            Hope that helps,
            John
            >
            Jan Kucera wrote:
            >Hi,
            > I have structure like this:
            >namespace Namespace
            >{
            > public class User
            > {
            > public Subnamespace.Se ttings Settings = new Subnamespace.Se ttings();
            > }
            > namespace Subnamespace
            > {
            > public class Settings
            > {
            > public string MyValue { get { return "Hello from there"; } }
            > }
            > public static class Helper
            > {
            > public static User User = new User();
            > }
            > }
            >}
            >>
            >now, I would like to get the value from string
            >"Namespace.Sub namespace.Helpe r.User.Settings .MyValue".
            >>
            >Reinout Waelput gave me on MSDN forums this code:
            >>
            >string Location = "MyNamespace.My Class.TheStruct .TheStruct2.MyV alue";
            >string s = Location.Substr ing(0, Location.IndexO f("."));
            >Location = Location.Substr ing(Location.In dexOf(".") + 1);
            >while (Type.GetType(s ) == null)
            >{
            >s = string.Concat(s , ".", Location.Substr ing(0, Location.IndexO f(".")));
            >Location = Location.Substr ing(Location.In dexOf(".") + 1);
            >}
            >System.Type pageType = Type.GetType(s) ;
            >System.Reflect ion.FieldInfo myField;
            >while (Location.Index Of(".") >= 1)
            >{
            >string str = Location.Substr ing(0, Location.IndexO f("."));
            >Location = Location.Substr ing(Location.In dexOf(".") + 1);
            >myField = pageType.GetFie ld(str);
            >pageType = myField.GetValu e(pageType).Get Type();
            >}
            >pageType.GetFi eld(Location, System.Reflecti on.BindingFlags .GetField);
            >>
            >Which works well, however fails in my case, probably because of the
            >Subnamespace.S ettings declaration. The exception is:
            >System.Argumen tException was unhandled
            > Field 'Settings' defined on type 'Namespace.User ' is not a field on the
            >target object which is of type 'System.Runtime Type'.
            > at System.Reflecti on.RtFieldInfo. CheckConsistenc y(Object target)
            > at System.Reflecti on.RtFieldInfo. InternalGetValu e(Object obj,
            >Boolean
            >doVisibilityCh eck, Boolean doCheckConsiste ncy)
            > at System.Reflecti on.RtFieldInfo. GetValue(Object obj)
            >>
            >VisualStudio during debug, when selecting
            >Namespace.Subn amespace.Helper .User.Settings. MyValue have no troubles.
            >>
            >Any idea how to handle the cross namespace declaration?
            >>
            >Thanks a lot,
            > Jan
            >

            Comment

            • Jan Kucera

              #7
              Re: Get member value by its name

              Hi Bruce.
              Thanks for your reply. All I want is to get the "Hello from there" string.
              Thanks for the hint with the instanced User. However... you have all the
              code I need to handle. So does it mean I should supply the previous value as
              a instance? Or where do I get the instance? Where does the VisualStudio?

              Thanks,
              Jan
              >
              I assume that you're getting the exception on the line that says:
              >
              pageType = myField.GetValu e(pageType).Get Type();
              >
              because the error is saying exactly what's wrong: pageType is an
              instance of System.Type, and System.Type has no field named "Settings".
              >
              The problem is that you're trying to get the _value_ of the "Settings"
              field from a Namespace.User instance, but you're not supplying an
              instance. Since there is a different value for "Settings" in every
              Namespace.User object, how can you get a value if you don't specify
              from which instance you want the value? You can do that only if
              "Settings" is static (and therefore there's only one shared between all
              instances), but it's not.
              >
              If you look at the other code posted on this thread, you'll see the
              line:
              >
              Namespace.User newUser = new Namespace.User( );
              >
              or something like that. That's the key. You have to create an instance
              in order to get the value of its "Settings" field.
              >
              On the other hand, if all you want is the type of Settings, you should
              do that like this:
              >
              ...
              myField = pageType.GetFie ld(str);
              pageType = myField.FieldTy pe;
              }
              pageType = pageType.GetFie ld(Location,
              System.Reflecti on.BindingFlags .GetField).Fiel dType;
              >
              In otherwords, don't call the GetValue() method; use the FieldType
              property instead.
              >

              Comment

              • John Duval

                #8
                Re: Get member value by its name

                Hi Jan,
                I should have guessed it was a harder problem than I first thought.

                I think Bruce hit the nail on the head when he said that you need to
                get an instance. Luckily, the Helper.User field is such an instance.

                This code I'm posting really should be made more generic (specifically
                the part that navigates down into User.Settings.M yValue). But in any
                case, here is some code that gets the "hello from there" string without
                knowing the field names:

                string input = "Namespace.Subn amespace.Helper .User.Settings. MyValue";

                string part1 = null, part2 = input;
                while (true)
                {
                part1 += ParseNextPart(r ef part2);
                if (part2 == null)
                break;
                if (Type.GetType(p art1) != null)
                break;
                part1 += ".";
                }

                // can probably turn these next 3 parts into a generic loop of some
                sort
                string nextPart = ParseNextPart(r ef part2);
                FieldInfo fieldInfo = Type.GetType(pa rt1).GetField(n extPart,
                BindingFlags.Pu blic | BindingFlags.St atic);
                object userInstance = fieldInfo.GetVa lue(null);

                nextPart = ParseNextPart(r ef part2);
                FieldInfo fieldInfo2 = userInstance.Ge tType().GetFiel d(nextPart,
                BindingFlags.Pu blic | BindingFlags.St atic);
                object settingsInstanc e = fieldInfo2.GetV alue(userInstan ce);

                nextPart = ParseNextPart(r ef part2);
                PropertyInfo propertyInfo =
                settingsInstanc e.GetType().Get Property(nextPa rt);
                object myValueInstance = propertyInfo.Ge tValue(settings Instance,
                null);

                And here's that ParseNextPart routine:

                static string ParseNextPart(r ef string input)
                {
                int dotIndex = input.IndexOf(' .');
                if (dotIndex == -1)
                dotIndex = input.Length;
                string ret = input.Substring (0, dotIndex);
                if (dotIndex + 1 input.Length)
                input = null;
                else
                input = input.Substring (dotIndex + 1);
                return ret;
                }

                Cleaning it up will be left as an exercise for the reader... :)
                Hope that helps,
                John

                Jan Kucera wrote:
                Hi John,
                unfortunately you assume I know the members declarations at design time.
                This is not true, I have to completely search the runtime types to find out
                the value as well as the VisualStudio does when hovering over the selected
                string during debug.
                Jan
                >
                "John Duval" <JohnMDuval@gma il.comwrote in message
                news:1152617005 .246204.232900@ h48g2000cwc.goo glegroups.com.. .
                Hi Jan,
                I was able to get the string "Hello from there" using this code:

                string inputString =
                "Namespace.Subn amespace.Helper .User.Settings. MyValue";
                int lastDot = inputString.Las tIndexOf('.');
                string typeName = inputString.Sub string(0, lastDot);
                string propertyName = inputString.Sub string(lastDot + 1);

                Namespace.User user = new Namespace.User( );
                Type userType = user.Settings.G etType();
                PropertyInfo pi = userType.GetPro perty(propertyN ame);
                object output = pi.GetValue(use r.Settings, null);

                There isn't really a problem with the embedded namespace that I saw.

                By the way, this code isn't very robust, since it assumes a lot about
                the input string. I'm not sure where you get your input string from,
                but it seems fragile to me to have to parse the string to separate the
                type from the property name. Perhaps the calling code already knows
                this information? If not, you'd probably want to add some error
                handling in case the property does not exist, or that kind of thing.

                Hope that helps,
                John

                Jan Kucera wrote:
                Hi,
                I have structure like this:
                namespace Namespace
                {
                public class User
                {
                public Subnamespace.Se ttings Settings = new Subnamespace.Se ttings();
                }
                namespace Subnamespace
                {
                public class Settings
                {
                public string MyValue { get { return "Hello from there"; } }
                }
                public static class Helper
                {
                public static User User = new User();
                }
                }
                }
                >
                now, I would like to get the value from string
                "Namespace.Subn amespace.Helper .User.Settings. MyValue".
                >
                Reinout Waelput gave me on MSDN forums this code:
                >
                string Location = "MyNamespace.My Class.TheStruct .TheStruct2.MyV alue";
                string s = Location.Substr ing(0, Location.IndexO f("."));
                Location = Location.Substr ing(Location.In dexOf(".") + 1);
                while (Type.GetType(s ) == null)
                {
                s = string.Concat(s , ".", Location.Substr ing(0, Location.IndexO f(".")));
                Location = Location.Substr ing(Location.In dexOf(".") + 1);
                }
                System.Type pageType = Type.GetType(s) ;
                System.Reflecti on.FieldInfo myField;
                while (Location.Index Of(".") >= 1)
                {
                string str = Location.Substr ing(0, Location.IndexO f("."));
                Location = Location.Substr ing(Location.In dexOf(".") + 1);
                myField = pageType.GetFie ld(str);
                pageType = myField.GetValu e(pageType).Get Type();
                }
                pageType.GetFie ld(Location, System.Reflecti on.BindingFlags .GetField);
                >
                Which works well, however fails in my case, probably because of the
                Subnamespace.Se ttings declaration. The exception is:
                System.Argument Exception was unhandled
                Field 'Settings' defined on type 'Namespace.User ' is not a field on the
                target object which is of type 'System.Runtime Type'.
                at System.Reflecti on.RtFieldInfo. CheckConsistenc y(Object target)
                at System.Reflecti on.RtFieldInfo. InternalGetValu e(Object obj,
                Boolean
                doVisibilityChe ck, Boolean doCheckConsiste ncy)
                at System.Reflecti on.RtFieldInfo. GetValue(Object obj)
                >
                VisualStudio during debug, when selecting
                Namespace.Subna mespace.Helper. User.Settings.M yValue have no troubles.
                >
                Any idea how to handle the cross namespace declaration?
                >
                Thanks a lot,
                Jan

                Comment

                • Jan Kucera

                  #9
                  Re: Get member value by its name

                  Hi folks!
                  Thanks to John Duval and Bruce Wood I was able to manage the code that
                  works and I believe is more general. The string manipulation could be
                  cleared but this was not the aim.
                  For all whose are intersted:

                  public static object DebugWatch(stri ng type)
                  {
                  string Location = type;
                  string s = Location.Substr ing(0, Location.IndexO f("."));
                  Location = Location.Substr ing(Location.In dexOf(".") + 1);
                  while (Type.GetType(s ) == null)
                  {
                  s = string.Concat(s , ".", Location.Substr ing(0, Location.IndexO f(".")));
                  Location = Location.Substr ing(Location.In dexOf(".") + 1);
                  }
                  System.Type pageType = Type.GetType(s) ;
                  System.Reflecti on.MemberInfo[] myMember;
                  object value = null;
                  Location += ".";
                  while (Location.Index Of(".") >= 1)
                  {
                  string str = Location.Substr ing(0, Location.IndexO f("."));
                  Location = Location.Substr ing(Location.In dexOf(".") + 1);
                  myMember = pageType.GetMem ber(str);
                  if (myMember.Lengt h < 1) return null;
                  else
                  switch (myMember[0].MemberType)
                  {
                  case System.Reflecti on.MemberTypes. Field:
                  value = ((System.Reflec tion.FieldInfo) myMember[0]).GetValue(valu e);
                  break;
                  case System.Reflecti on.MemberTypes. Property:
                  value = ((System.Reflec tion.PropertyIn fo)myMember[0]).GetValue(valu e,
                  null);
                  break;
                  }
                  pageType = value.GetType() ;
                  }
                  return value;
                  }

                  So thank you all!

                  Comment

                  Working...