Inconsistant null parameter handling in Reflection

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Stefan Hong

    Inconsistant null parameter handling in Reflection

    Hi,

    It seems that the way reflection resolves methods is not quite the same as
    default CLR. For example this simple class:

    class Test {
    public void Hello(string name) {
    Console.WriteLi ne("Hello(strin g)");
    }
    public void Hello(object obj) {
    Console.WriteLi ne("Hello(objec t)");
    }
    }

    If I invoke the method normally using null parameter:

    Test test = new Test();
    test.Hello(null ); // shows Hello(string)

    But if I only know the input parameter (which is null) and the name of the
    method, and trying to use reflection to resolve the method to invoke, it
    becomes:

    Test test = new Test();
    MethodInfo method = test.GetType(). GetMethod("Hell o", new Type[] {
    typeof(void) });
    method.invoke(t est, new object[] { null }); // shows Hello(object)

    The result changed. It must because of the typeof(void) thing, but I can't
    say typeof(string) because the input parameter is null. What should I do to
    get the same result?


    Thanks,
    Stefan


  • Jon Skeet [C# MVP]

    #2
    Re: Inconsistant null parameter handling in Reflection

    Stefan Hong <stefan@mosp.ne t> wrote:[color=blue]
    > It seems that the way reflection resolves methods is not quite the same as
    > default CLR.[/color]

    It's not the CLR that decides which overload to call in the statically
    compiled case - it's the C# compiler.

    <snip>
    [color=blue]
    > But if I only know the input parameter (which is null) and the name of the
    > method, and trying to use reflection to resolve the method to invoke, it
    > becomes:
    >
    > Test test = new Test();
    > MethodInfo method = test.GetType(). GetMethod("Hell o", new Type[] {
    > typeof(void) });
    > method.invoke(t est, new object[] { null }); // shows Hello(object)
    >
    > The result changed. It must because of the typeof(void) thing, but I can't
    > say typeof(string) because the input parameter is null. What should I do to
    > get the same result?[/color]

    You can still use typeof(string) even if the input parameter is null.
    (I'm surprised you can get away with typeof(void) in the above, to be
    honest.)

    If you only receive null and you basically don't know which method to
    call, but you want to call the most specific method, you'll need to
    call Type.GetMethods and work out which one to call for yourself.

    --
    Jon Skeet - <skeet@pobox.co m>
    Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

    If replying to the group, please do not mail me too

    Comment

    • Stefan Hong

      #3
      Re: Inconsistant null parameter handling in Reflection

      "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote in message
      news:MPG.1bfaa3 c4a1f2a82198b89 9@msnews.micros oft.com...[color=blue]
      > Stefan Hong <stefan@mosp.ne t> wrote:[color=green]
      >> It seems that the way reflection resolves methods is not quite the same
      >> as
      >> default CLR.[/color]
      >
      > It's not the CLR that decides which overload to call in the statically
      > compiled case - it's the C# compiler.
      >[/color]

      <snip>
      [color=blue]
      >
      > You can still use typeof(string) even if the input parameter is null.
      > (I'm surprised you can get away with typeof(void) in the above, to be
      > honest.)
      >
      > If you only receive null and you basically don't know which method to
      > call, but you want to call the most specific method, you'll need to
      > call Type.GetMethods and work out which one to call for yourself.
      >[/color]

      Hmm... to completely mimic the type binding rule used by C# compiler seems
      not easy and error-prone, is there a such Binder class exists in the .net
      framework library already?


      Thanks,
      Stefan


      Comment

      • Jon Skeet [C# MVP]

        #4
        Re: Inconsistant null parameter handling in Reflection

        Stefan Hong <stefan@mosp.ne t> wrote:[color=blue][color=green]
        > > If you only receive null and you basically don't know which method to
        > > call, but you want to call the most specific method, you'll need to
        > > call Type.GetMethods and work out which one to call for yourself.[/color]
        >
        > Hmm... to completely mimic the type binding rule used by C# compiler seems
        > not easy and error-prone, is there a such Binder class exists in the .net
        > framework library already?[/color]

        I don't believe so, I'm afraid. I would try to avoid it, personally,
        but it's hard to know exactly what that entails without having more
        information about your problem.

        --
        Jon Skeet - <skeet@pobox.co m>
        Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

        If replying to the group, please do not mail me too

        Comment

        • Robert Jordan

          #5
          Re: Inconsistant null parameter handling in Reflection

          Hi,
          [color=blue]
          > Test test = new Test();
          > MethodInfo method = test.GetType(). GetMethod("Hell o", new Type[] {
          > typeof(void) });
          > method.invoke(t est, new object[] { null }); // shows Hello(object)[/color]

          You should try

          test.GetType(). InvokeMember(
          "Hello", BindingFlags.Pu blic, null, test, new object[] {null}
          );

          The default binder will be applied and I'd bet, that it
          will dispatch to the correct method.

          bye
          Rob

          Comment

          • Stefan Hong

            #6
            Re: Inconsistant null parameter handling in Reflection

            "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote:[color=blue]
            > Stefan Hong <stefan@mosp.ne t> wrote:[color=green][color=darkred]
            >> > If you only receive null and you basically don't know which method to
            >> > call, but you want to call the most specific method, you'll need to
            >> > call Type.GetMethods and work out which one to call for yourself.[/color]
            >>
            >> Hmm... to completely mimic the type binding rule used by C# compiler
            >> seems
            >> not easy and error-prone, is there a such Binder class exists in the .net
            >> framework library already?[/color]
            >
            > I don't believe so, I'm afraid. I would try to avoid it, personally,
            > but it's hard to know exactly what that entails without having more
            > information about your problem.[/color]

            I am experimenting a new remote invocation protocol, similar to what web
            services can do but is a completely different thing. I can unwrap the
            invocation request at the remote site to get the name of the method and an
            array of unmarshalled parameter objects, but then I can not find the right
            method to invoke, especially when there is null among input parameters.


            Stefan


            Comment

            • Stefan Hong

              #7
              Re: Inconsistant null parameter handling in Reflection

              "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote:[color=blue]
              > Stefan Hong <stefan@mosp.ne t> wrote:[color=green][color=darkred]
              >> > If you only receive null and you basically don't know which method to
              >> > call, but you want to call the most specific method, you'll need to
              >> > call Type.GetMethods and work out which one to call for yourself.[/color]
              >>
              >> Hmm... to completely mimic the type binding rule used by C# compiler
              >> seems
              >> not easy and error-prone, is there a such Binder class exists in the .net
              >> framework library already?[/color]
              >
              > I don't believe so, I'm afraid. I would try to avoid it, personally,
              > but it's hard to know exactly what that entails without having more
              > information about your problem.[/color]

              I am experimenting a new remote invocation protocol, similar to what web
              services can do but is a completely different thing. I can unwrap the
              invocation request at the remote site to get the name of the method and an
              array of unmarshalled parameter objects, but then I can not find the right
              method to invoke, especially when there is null among input parameters.


              Stefan


              Comment

              • Stefan Hong

                #8
                Re: Inconsistant null parameter handling in Reflection


                "Robert Jordan" <robertj@gmx.ne t> wrote:[color=blue]
                > Hi,
                > You should try
                >
                > test.GetType(). InvokeMember(
                > "Hello", BindingFlags.Pu blic, null, test, new object[] {null}
                > );
                >
                > The default binder will be applied and I'd bet, that it
                > will dispatch to the correct method.[/color]

                I tried do this:

                test.GetType(). InvokeMember(
                "Hello",
                BindingFlags.Pu blic | BindingFlags.In vokeMethod,
                null, test, new object[] {null});

                But I got a MissingMethodEx ception says:

                "Attempted to access a missing member"

                Any idea?


                Thanks,
                Stefan


                Comment

                • Stefan Hong

                  #9
                  Re: Inconsistant null parameter handling in Reflection


                  "Robert Jordan" <robertj@gmx.ne t> wrote:[color=blue]
                  > Hi,
                  > You should try
                  >
                  > test.GetType(). InvokeMember(
                  > "Hello", BindingFlags.Pu blic, null, test, new object[] {null}
                  > );
                  >
                  > The default binder will be applied and I'd bet, that it
                  > will dispatch to the correct method.[/color]

                  I tried do this:

                  test.GetType(). InvokeMember(
                  "Hello",
                  BindingFlags.Pu blic | BindingFlags.In vokeMethod,
                  null, test, new object[] {null});

                  But I got a MissingMethodEx ception says:

                  "Attempted to access a missing member"

                  Any idea?


                  Thanks,
                  Stefan


                  Comment

                  • Stefan Hong

                    #10
                    Re: Inconsistant null parameter handling in Reflection


                    "Stefan Hong" <stefan@mosp.ne t> wrote:[color=blue]
                    > I tried do this:
                    >
                    > test.GetType(). InvokeMember(
                    > "Hello",
                    > BindingFlags.Pu blic | BindingFlags.In vokeMethod,
                    > null, test, new object[] {null});
                    >
                    > But I got a MissingMethodEx ception says:
                    >
                    > "Attempted to access a missing member"
                    >
                    > Any idea?
                    >[/color]

                    I've played with the BindingFlags and now I can invoke the correct method
                    with this:

                    test.GetType(). InvokeMember(
                    "Hello",
                    BindingFlags.Pu blic | BindingFlags.In vokeMethod | BindingFlags.In stance,
                    null, test, new object[] {null});

                    I tried to apply the same thing to test.GetType(). GetMethod( ... ) but
                    wasn't able to get the same result. I must get MethodInfo before invoking
                    'cause I want to check some custom attributes first.

                    This could be a design flaw of Reflection because there is no way to specify
                    the type of null reference. I thought typeof(void) could do the trick but
                    it couldn't. Maybe we need something like typeof(null) supported by C#
                    compiler or Type.Null in the framework.


                    Stefan


                    Comment

                    • Stefan Hong

                      #11
                      Re: Inconsistant null parameter handling in Reflection


                      "Stefan Hong" <stefan@mosp.ne t> wrote:[color=blue]
                      > I tried do this:
                      >
                      > test.GetType(). InvokeMember(
                      > "Hello",
                      > BindingFlags.Pu blic | BindingFlags.In vokeMethod,
                      > null, test, new object[] {null});
                      >
                      > But I got a MissingMethodEx ception says:
                      >
                      > "Attempted to access a missing member"
                      >
                      > Any idea?
                      >[/color]

                      I've played with the BindingFlags and now I can invoke the correct method
                      with this:

                      test.GetType(). InvokeMember(
                      "Hello",
                      BindingFlags.Pu blic | BindingFlags.In vokeMethod | BindingFlags.In stance,
                      null, test, new object[] {null});

                      I tried to apply the same thing to test.GetType(). GetMethod( ... ) but
                      wasn't able to get the same result. I must get MethodInfo before invoking
                      'cause I want to check some custom attributes first.

                      This could be a design flaw of Reflection because there is no way to specify
                      the type of null reference. I thought typeof(void) could do the trick but
                      it couldn't. Maybe we need something like typeof(null) supported by C#
                      compiler or Type.Null in the framework.


                      Stefan


                      Comment

                      • Jon Skeet [C# MVP]

                        #12
                        Re: Inconsistant null parameter handling in Reflection

                        Stefan Hong <stefan@mosp.ne t> wrote:[color=blue]
                        > I've played with the BindingFlags and now I can invoke the correct method
                        > with this:
                        >
                        > test.GetType(). InvokeMember(
                        > "Hello",
                        > BindingFlags.Pu blic | BindingFlags.In vokeMethod | BindingFlags.In stance,
                        > null, test, new object[] {null});
                        >
                        > I tried to apply the same thing to test.GetType(). GetMethod( ... ) but
                        > wasn't able to get the same result. I must get MethodInfo before invoking
                        > 'cause I want to check some custom attributes first.
                        >
                        > This could be a design flaw of Reflection because there is no way to specify
                        > the type of null reference. I thought typeof(void) could do the trick but
                        > it couldn't. Maybe we need something like typeof(null) supported by C#
                        > compiler or Type.Null in the framework.[/color]

                        No, because you don't *want* a typeof(null) or typeof(void). You want
                        to say what the declared parameter type is - eg typeof(string).

                        --
                        Jon Skeet - <skeet@pobox.co m>
                        Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                        If replying to the group, please do not mail me too

                        Comment

                        • Jon Skeet [C# MVP]

                          #13
                          Re: Inconsistant null parameter handling in Reflection

                          Stefan Hong <stefan@mosp.ne t> wrote:[color=blue]
                          > I've played with the BindingFlags and now I can invoke the correct method
                          > with this:
                          >
                          > test.GetType(). InvokeMember(
                          > "Hello",
                          > BindingFlags.Pu blic | BindingFlags.In vokeMethod | BindingFlags.In stance,
                          > null, test, new object[] {null});
                          >
                          > I tried to apply the same thing to test.GetType(). GetMethod( ... ) but
                          > wasn't able to get the same result. I must get MethodInfo before invoking
                          > 'cause I want to check some custom attributes first.
                          >
                          > This could be a design flaw of Reflection because there is no way to specify
                          > the type of null reference. I thought typeof(void) could do the trick but
                          > it couldn't. Maybe we need something like typeof(null) supported by C#
                          > compiler or Type.Null in the framework.[/color]

                          No, because you don't *want* a typeof(null) or typeof(void). You want
                          to say what the declared parameter type is - eg typeof(string).

                          --
                          Jon Skeet - <skeet@pobox.co m>
                          Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.

                          If replying to the group, please do not mail me too

                          Comment

                          • Stefan Hong

                            #14
                            Re: Inconsistant null parameter handling in Reflection

                            "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote;[color=blue]
                            > Stefan Hong <stefan@mosp.ne t> wrote:[color=green]
                            >>
                            >> This could be a design flaw of Reflection because there is no way to
                            >> specify
                            >> the type of null reference. I thought typeof(void) could do the trick
                            >> but
                            >> it couldn't. Maybe we need something like typeof(null) supported by C#
                            >> compiler or Type.Null in the framework.[/color]
                            >
                            > No, because you don't *want* a typeof(null) or typeof(void). You want
                            > to say what the declared parameter type is - eg typeof(string).[/color]

                            If I already know the declared parameter type is string, I would definitely
                            use typeof(string). But in my case I don't. All I know is the name of the
                            method and the parameter objects. Default binder can resolve method without
                            any problem, so we can do:

                            test.Hello( null );

                            The null is just nothing, no declared type. Binder knows how to escalate
                            null to the most specific type. The problem is when we want to resolve the
                            MethodInfo using the same binding rule, there is no way to tell binder that
                            we have a null parameter to let binder do the escalation magic. That's why
                            I think a pseudo Type.Null or typeof(null) might be necessary.


                            Stefan


                            Comment

                            • Stefan Hong

                              #15
                              Re: Inconsistant null parameter handling in Reflection

                              "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote;[color=blue]
                              > Stefan Hong <stefan@mosp.ne t> wrote:[color=green]
                              >>
                              >> This could be a design flaw of Reflection because there is no way to
                              >> specify
                              >> the type of null reference. I thought typeof(void) could do the trick
                              >> but
                              >> it couldn't. Maybe we need something like typeof(null) supported by C#
                              >> compiler or Type.Null in the framework.[/color]
                              >
                              > No, because you don't *want* a typeof(null) or typeof(void). You want
                              > to say what the declared parameter type is - eg typeof(string).[/color]

                              If I already know the declared parameter type is string, I would definitely
                              use typeof(string). But in my case I don't. All I know is the name of the
                              method and the parameter objects. Default binder can resolve method without
                              any problem, so we can do:

                              test.Hello( null );

                              The null is just nothing, no declared type. Binder knows how to escalate
                              null to the most specific type. The problem is when we want to resolve the
                              MethodInfo using the same binding rule, there is no way to tell binder that
                              we have a null parameter to let binder do the escalation magic. That's why
                              I think a pseudo Type.Null or typeof(null) might be necessary.


                              Stefan


                              Comment

                              Working...