using reflection to discover a nested structure

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Bill Grigg

    using reflection to discover a nested structure

    All,

    Can anyone supply an example or reference to an example of using
    reflection to determine the data types and array lengths contained in a
    nested stucture in C#? Actually, it is a structure that I use to communicate
    to some unmanaged code in a DLL written in C. It is not complicated, but will
    change and I would like to be able to sequentially access it without
    explicitly referring to each and every element. Here is the structure:

    [StructLayout(La youtKind.Sequen tial)]
    unsafe public struct MyOutputs
    {
    [StructLayout(La youtKind.Sequen tial)]
    unsafe public struct TelemListA
    {
    public double navTime;
    public double navMode;
    public Outputs outputs;
    }
    [StructLayout(La youtKind.Sequen tial)]
    unsafe public struct Outputs
    {
    public fixed double Q_isa[4];
    public fixed double dV[3];
    public fixed double dT[3];
    public fixed double Q_mid[4];
    }
    }

    Once I get the list of MemberInfo[] and determine that
    MemberInfo[i].MemberType.ToS tring().Equals( "NestedType "), I cannot
    figure out how to drill down from that point.


    TIA,


    Bill

  • Jon Shemitz

    #2
    Re: using reflection to discover a nested structure

    Bill Grigg wrote:
    Once I get the list of MemberInfo[] and determine that
    MemberInfo[i].MemberType.ToS tring().Equals( "NestedType "), I cannot
    figure out how to drill down from that point.
    In that case, the MemberInfo is a Type. For example,

    private static void ListMembers(Typ e T)
    {
    foreach (MemberInfo Member in T.GetMembers())
    {
    if (Member.Declari ngType == T)
    Console.WriteLi ne("{0}.{1}", T.FullName, Member.Name);
    if (Member is Type)
    ListMembers((Ty pe)Member);
    }
    }

    --

    ..NET 2.0 for Delphi Programmers www.midnightbeach.com/.net
    Delphi skills make .NET easy to learn Great reviews & good sales.

    Comment

    • Bill Grigg

      #3
      Re: using reflection to discover a nested structure

      Jon,

      Thanks, that helped a lot. Now I have (I think) just one more question:

      Given that I have drilled down and found the fields in an instantiated
      object (well, a stucture of doubles actually), I would like to either read
      the values of the fields, or store something into them. When I found
      field.SetValue( ...) I thought I was all set except that it is
      field.SetValue( obj x, obj value). Now I cannot figure out what's the field
      and what's the object. I did the following:

      Type t = Member.GetType( );
      FieldInfo field = t.GetField(Memb er.Name);
      field.SetValue( now what do I do???);

      TIA

      Bill

      "Jon Shemitz" wrote:
      Bill Grigg wrote:
      >
      Once I get the list of MemberInfo[] and determine that
      MemberInfo[i].MemberType.ToS tring().Equals( "NestedType "), I cannot
      figure out how to drill down from that point.
      >
      In that case, the MemberInfo is a Type. For example,
      >
      private static void ListMembers(Typ e T)
      {
      foreach (MemberInfo Member in T.GetMembers())
      {
      if (Member.Declari ngType == T)
      Console.WriteLi ne("{0}.{1}", T.FullName, Member.Name);
      if (Member is Type)
      ListMembers((Ty pe)Member);
      }
      }
      >
      --
      >
      ..NET 2.0 for Delphi Programmers www.midnightbeach.com/.net
      Delphi skills make .NET easy to learn Great reviews & good sales.
      >

      Comment

      • Jon Shemitz

        #4
        Re: using reflection to discover a nested structure

        Bill Grigg wrote:
        Given that I have drilled down and found the fields in an instantiated
        object (well, a stucture of doubles actually), I would like to either read
        the values of the fields, or store something into them. When I found
        field.SetValue( ...) I thought I was all set except that it is
        field.SetValue( obj x, obj value). Now I cannot figure out what's the field
        and what's the object. I did the following:
        Hmm, the docs seem pretty clear, to me:

        public void SetValue (
        Object obj,
        Object value
        )

        obj
        The object whose field value will be set.

        value
        The value to assign to the field.

        That is, it's modeled on assignment. Field.SetValue( Instance,
        NewValue) sets Instance.Field to NewValue.

        --

        ..NET 2.0 for Delphi Programmers www.midnightbeach.com/.net
        Delphi skills make .NET easy to learn Great reviews & good sales.

        Comment

        • Bill Grigg

          #5
          Re: using reflection to discover a nested structure

          I guess I am having another mental block. WRT the following snippet:


          Type t = Member.GetType( );
          FieldInfo field = t.GetField(Memb er.Name);
          field.SetValue( now what do I do???);

          1. As far as I can figure out "field" is the field in my data structure. To
          be more specific let's say the structure is:

          struct Inputs {
          double arr1[3];
          double dt;
          double arr2[3];
          };

          and I have located "dt". How do I read/write "dt"?

          2. The only "SetValue() " that I can find is the one belonging to "field". So
          if I write:

          field.SetValue( ???, 1.2345); // What is ??? supposed to be?

          3. Unless I am missing a namespace reference there is no
          FieldInfo.SetVa lue(...) and the is no plan old SetValue(...).

          "Bill Grigg" wrote:
          Jon,
          >
          Thanks, that helped a lot. Now I have (I think) just one more question:
          >
          Given that I have drilled down and found the fields in an instantiated
          object (well, a stucture of doubles actually), I would like to either read
          the values of the fields, or store something into them. When I found
          field.SetValue( ...) I thought I was all set except that it is
          field.SetValue( obj x, obj value). Now I cannot figure out what's the field
          and what's the object. I did the following:
          >
          Type t = Member.GetType( );
          FieldInfo field = t.GetField(Memb er.Name);
          field.SetValue( now what do I do???);
          >
          TIA
          >
          Bill
          >
          "Jon Shemitz" wrote:
          >
          Bill Grigg wrote:
          Once I get the list of MemberInfo[] and determine that
          MemberInfo[i].MemberType.ToS tring().Equals( "NestedType "), I cannot
          figure out how to drill down from that point.
          In that case, the MemberInfo is a Type. For example,

          private static void ListMembers(Typ e T)
          {
          foreach (MemberInfo Member in T.GetMembers())
          {
          if (Member.Declari ngType == T)
          Console.WriteLi ne("{0}.{1}", T.FullName, Member.Name);
          if (Member is Type)
          ListMembers((Ty pe)Member);
          }
          }

          --

          ..NET 2.0 for Delphi Programmers www.midnightbeach.com/.net
          Delphi skills make .NET easy to learn Great reviews & good sales.

          Comment

          • Jon Shemitz

            #6
            Re: using reflection to discover a nested structure

            Bill Grigg wrote:
            >
            I guess I am having another mental block. WRT the following snippet:
            >
            Type t = Member.GetType( );
            FieldInfo field = t.GetField(Memb er.Name);
            field.SetValue( now what do I do???);
            field.SetValue( Member, 1.2345);
            1. As far as I can figure out "field" is the field in my data structure. To
            be more specific let's say the structure is:
            >
            struct Inputs {
            double arr1[3];
            double dt;
            double arr2[3];
            };
            >
            and I have located "dt". How do I read/write "dt"?
            Type MemberType = Member.GetType( );
            FieldInfo dtField = MemberType.GetF ield("dt");

            // Read Member.Field
            double CurrentValue = (double) dtField.GetValu e(Member);

            // Write Member.Field
            dtfield.SetValu e(Member, 1.2345);
            2. The only "SetValue() " that I can find is the one belonging to "field". So
            if I write:
            >
            field.SetValue( ???, 1.2345); // What is ??? supposed to be?
            An object reference.
            3. Unless I am missing a namespace reference there is no
            FieldInfo.SetVa lue(...) and the is no plan old SetValue(...).
            System.Reflecti on.

            --

            ..NET 2.0 for Delphi Programmers www.midnightbeach.com/.net
            Delphi skills make .NET easy to learn Great reviews & good sales.

            Comment

            • Bill Grigg

              #7
              Re: using reflection to discover a nested structure

              Jon,

              I appreciate the help. I think the fundamental problem was that I was not
              working with an instance of the object (i.e. my data structure). In any case
              the following works ("inputs" is an instance of the data structure):

              Type myType = inputs.GetType( );
              MemberInfo[] m= myType.GetMembe rs();
              Object obj = myType.InvokeMe mber(m[9].Name, BindingFlags.Ge tField,
              null, inputs, null); // I use m[9] because I cheated and found tolut hat is
              where "dt" is

              The obj object contains the value of "dt" mention earlier. Now I cannot
              figure out how to set the value of "dt". If I write:

              Object[] objA = new object[] { 2.777 };
              o = myType.InvokeMe mber(myMemberIn fo[9].Name, BindingFlags.Se tField,
              null, intIMUIn, objA);

              the field "dt" remains unchanged.

              By the way, the reason that I am doing this is that I will be testing a
              series of functions with input parameters that are basically structures of
              nested "doubles". I will be receiving input vectors for these functions that
              have these doubles arranged in the order that they appear in the structures.
              I do not want to have to reference each element of each structure
              "explicitly " because there will be literally hundreds of input "doubles" in
              some cases. All of the functions are written in C (unmanaged) and reside in a
              DLL that fortunately I can build into my Solution.

              One other issue - most of the elements of the structures are arrays, so I
              need to find out how to reference each element of a nested array through
              reflection.

              Hope this is not too confusing...

              Thanks,

              Bill


              "Jon Shemitz" wrote:
              Bill Grigg wrote:

              I guess I am having another mental block. WRT the following snippet:

              Type t = Member.GetType( );
              FieldInfo field = t.GetField(Memb er.Name);
              field.SetValue( now what do I do???);
              >
              field.SetValue( Member, 1.2345);
              >
              1. As far as I can figure out "field" is the field in my data structure. To
              be more specific let's say the structure is:

              struct Inputs {
              double arr1[3];
              double dt;
              double arr2[3];
              };

              and I have located "dt". How do I read/write "dt"?
              >
              Type MemberType = Member.GetType( );
              FieldInfo dtField = MemberType.GetF ield("dt");
              >
              // Read Member.Field
              double CurrentValue = (double) dtField.GetValu e(Member);
              >
              // Write Member.Field
              dtfield.SetValu e(Member, 1.2345);
              >
              2. The only "SetValue() " that I can find is the one belonging to "field". So
              if I write:

              field.SetValue( ???, 1.2345); // What is ??? supposed to be?
              >
              An object reference.
              >
              3. Unless I am missing a namespace reference there is no
              FieldInfo.SetVa lue(...) and the is no plan old SetValue(...).
              >
              System.Reflecti on.
              >
              --
              >
              ..NET 2.0 for Delphi Programmers www.midnightbeach.com/.net
              Delphi skills make .NET easy to learn Great reviews & good sales.
              >

              Comment

              • Bill Grigg

                #8
                Re: using reflection to discover a nested structure

                Jon,

                I just discovered that it works if it is a managed data structure!!! Do I
                have a chance of doing this if the structure is declared thusly:

                [StructLayout(La youtKind.Sequen tial)]
                unsafe public struct Inputs
                {
                [StructLayout(La youtKind.Sequen tial)]
                unsafe public struct MyInputs
                {
                public fixed double array1[3];
                public fixed double array2[3];
                public double dt;
                public fixed double array3[3];
                }
                }


                "Bill Grigg" wrote:
                Jon,
                >
                I appreciate the help. I think the fundamental problem was that I was not
                working with an instance of the object (i.e. my data structure). In any case
                the following works ("inputs" is an instance of the data structure):
                >
                Type myType = inputs.GetType( );
                MemberInfo[] m= myType.GetMembe rs();
                Object obj = myType.InvokeMe mber(m[9].Name, BindingFlags.Ge tField,
                null, inputs, null); // I use m[9] because I cheated and found tolut hat is
                where "dt" is
                >
                The obj object contains the value of "dt" mention earlier. Now I cannot
                figure out how to set the value of "dt". If I write:
                >
                Object[] objA = new object[] { 2.777 };
                o = myType.InvokeMe mber(myMemberIn fo[9].Name, BindingFlags.Se tField,
                null, intIMUIn, objA);
                >
                the field "dt" remains unchanged.
                >
                By the way, the reason that I am doing this is that I will be testing a
                series of functions with input parameters that are basically structures of
                nested "doubles". I will be receiving input vectors for these functions that
                have these doubles arranged in the order that they appear in the structures.
                I do not want to have to reference each element of each structure
                "explicitly " because there will be literally hundreds of input "doubles" in
                some cases. All of the functions are written in C (unmanaged) and reside in a
                DLL that fortunately I can build into my Solution.
                >
                One other issue - most of the elements of the structures are arrays, so I
                need to find out how to reference each element of a nested array through
                reflection.
                >
                Hope this is not too confusing...
                >
                Thanks,
                >
                Bill
                >
                >
                "Jon Shemitz" wrote:
                >
                Bill Grigg wrote:
                >
                I guess I am having another mental block. WRT the following snippet:
                >
                Type t = Member.GetType( );
                FieldInfo field = t.GetField(Memb er.Name);
                field.SetValue( now what do I do???);
                field.SetValue( Member, 1.2345);
                1. As far as I can figure out "field" is the field in my data structure. To
                be more specific let's say the structure is:
                >
                struct Inputs {
                double arr1[3];
                double dt;
                double arr2[3];
                };
                >
                and I have located "dt". How do I read/write "dt"?
                Type MemberType = Member.GetType( );
                FieldInfo dtField = MemberType.GetF ield("dt");

                // Read Member.Field
                double CurrentValue = (double) dtField.GetValu e(Member);

                // Write Member.Field
                dtfield.SetValu e(Member, 1.2345);
                2. The only "SetValue() " that I can find is the one belonging to "field". So
                if I write:
                >
                field.SetValue( ???, 1.2345); // What is ??? supposed to be?
                An object reference.
                3. Unless I am missing a namespace reference there is no
                FieldInfo.SetVa lue(...) and the is no plan old SetValue(...).
                System.Reflecti on.

                --

                ..NET 2.0 for Delphi Programmers www.midnightbeach.com/.net
                Delphi skills make .NET easy to learn Great reviews & good sales.

                Comment

                • Jon Shemitz

                  #9
                  Re: using reflection to discover a nested structure

                  Bill Grigg wrote:
                  I just discovered that it works if it is a managed data structure!!! Do I
                  have a chance of doing this if the structure is declared thusly:
                  >
                  [StructLayout(La youtKind.Sequen tial)]
                  unsafe public struct Inputs
                  {
                  [StructLayout(La youtKind.Sequen tial)]
                  unsafe public struct MyInputs
                  {
                  public fixed double array1[3];
                  public fixed double array2[3];
                  public double dt;
                  public fixed double array3[3];
                  }
                  }
                  Type myType = inputs.GetType( );
                  MemberInfo[] m= myType.GetMembe rs();
                  Object obj = myType.InvokeMe mber(m[9].Name, BindingFlags.Ge tField,
                  null, inputs, null);
                  Object[] objA = new object[] { 2.777 };
                  o = myType.InvokeMe mber(myMemberIn fo[9].Name, BindingFlags.Se tField,
                  null, intIMUIn, objA);

                  the field "dt" remains unchanged.
                  I'm not sure what's going on, and don't currently have the time to run
                  some experiments. (Maybe later.)

                  I don't think I'd be using InvokeMember, here: I'd be more inclined to
                  use the lower level Reflection primitives, like GetField and SetValue.
                  It's probably more efficient (certainly there are no object arrays
                  involved) and you may have more control.

                  On the InvokeMember front, though, I guess I'd investigate the use of
                  a Binder object (instead of a null 4th parameter). I don't know why
                  your code works on safe structs but not unsafe structs - there may be
                  some name hashing going on, and the Binder object may be able to make
                  some appropriate decisions.
                  One other issue - most of the elements of the structures are arrays, so I
                  need to find out how to reference each element of a nested array through
                  reflection.
                  Again, I'll have to get back to you after I have some time for a few
                  experiments.

                  --

                  ..NET 2.0 for Delphi Programmers www.midnightbeach.com/.net
                  Delphi skills make .NET easy to learn Great reviews & good sales.

                  Comment

                  • Bill Grigg

                    #10
                    Re: using reflection to discover a nested structure

                    Jon,

                    I found the answer. I needed to "box" the input structure and hence make it
                    "managed".

                    Bill

                    "Jon Shemitz" wrote:
                    Bill Grigg wrote:
                    >
                    I just discovered that it works if it is a managed data structure!!! Do I
                    have a chance of doing this if the structure is declared thusly:

                    [StructLayout(La youtKind.Sequen tial)]
                    unsafe public struct Inputs
                    {
                    [StructLayout(La youtKind.Sequen tial)]
                    unsafe public struct MyInputs
                    {
                    public fixed double array1[3];
                    public fixed double array2[3];
                    public double dt;
                    public fixed double array3[3];
                    }
                    }
                    >
                    Type myType = inputs.GetType( );
                    MemberInfo[] m= myType.GetMembe rs();
                    Object obj = myType.InvokeMe mber(m[9].Name, BindingFlags.Ge tField,
                    null, inputs, null);
                    >
                    Object[] objA = new object[] { 2.777 };
                    o = myType.InvokeMe mber(myMemberIn fo[9].Name, BindingFlags.Se tField,
                    null, intIMUIn, objA);
                    >
                    the field "dt" remains unchanged.
                    >
                    I'm not sure what's going on, and don't currently have the time to run
                    some experiments. (Maybe later.)
                    >
                    I don't think I'd be using InvokeMember, here: I'd be more inclined to
                    use the lower level Reflection primitives, like GetField and SetValue.
                    It's probably more efficient (certainly there are no object arrays
                    involved) and you may have more control.
                    >
                    On the InvokeMember front, though, I guess I'd investigate the use of
                    a Binder object (instead of a null 4th parameter). I don't know why
                    your code works on safe structs but not unsafe structs - there may be
                    some name hashing going on, and the Binder object may be able to make
                    some appropriate decisions.
                    >
                    One other issue - most of the elements of the structures are arrays, so I
                    need to find out how to reference each element of a nested array through
                    reflection.
                    >
                    Again, I'll have to get back to you after I have some time for a few
                    experiments.
                    >
                    --
                    >
                    ..NET 2.0 for Delphi Programmers www.midnightbeach.com/.net
                    Delphi skills make .NET easy to learn Great reviews & good sales.
                    >

                    Comment

                    Working...