7 Replies - 322 Views - Last Post: 09 June 2012 - 09:31 PM Rate Topic: -----

#1 monkey_05_06  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 1
  • View blog
  • Posts: 105
  • Joined: 26-August 06

Reflection only finding 1 of 2 overloads.

Posted 09 June 2012 - 01:38 PM

Let me start off by saying that I realize this is probably not a typical user-case scenario, but that doesn't mean I have been negligent in my own debugging.

I am working on an extension to an existing program, but the main program's extension API doesn't expose a particular method that I am trying to access. I have the access to expose this to the API and submit the revision to the main code base, but I am interested in finding a resolution that works with the existing code as well.

Presently there is a class defined such as this in the main program (the class itself is not presently exposed to the API):

namespace Program
{
  class TextControl
  {
    // ...
    public void SetText(string newText)
    {
      SetText(newText, true);
    }

    public void SetText(string newText, bool clearModified)
    {
      // ...
    }
  }
}


I need to be able to leave the modified flag in-tact, so using the single-parameter overload is insufficient. Since the class and its methods are not exposed to the API, I am trying to use reflection to access the function:

try
{
  Type t = Assembly.GetEntryAssembly().GetType("Program.TextControl"); // this is working fine
  MethodInfo method = t.GetMethod("SetText", new Type[] { typeof(string), typeof(bool) });
  if (method == null) System.Windows.Forms.MessageBox.Show("Method not found.");
  else System.Windows.Forms.MessageBox.Show("Method " + method.Name + " found.");
}
catch (Exception e)
{
  System.Windows.Forms.MessageBox.Show("Error:" + Environment.NewLine + Environment.NewLine + e.Message);
}


This code is always showing "Method not found.". So no exceptions are being thrown, but the overloaded method is not being found. So I tried this:

try
{
  Type t = Assembly.GetEntryAssembly().GetType("Program.TextControl"); // this is working fine
  MethodInfo method = t.GetMethod("SetText", BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new Type[] { typeof(string), typeof(bool) }, new ParameterModifier[0]);
  if (method == null) System.Windows.Forms.MessageBox.Show("Method not found.");
  else System.Windows.Forms.MessageBox.Show("Method " + method.Name + " found.");
}
catch (Exception e)
{
  System.Windows.Forms.MessageBox.Show("Error:" + Environment.NewLine + Environment.NewLine + e.Message);
}


My results were identical. They were also identical if I pass null as the Binder or ParameterModifier[] parameters.

So from there I was somewhat stumped, but I decided to iterate through every method and see what was being found:

try
{
  Type t = Assembly.GetEntryAssembly().GetType("Program.TextControl"); // this is working fine
  foreach (MethodInfo method in t.GetMethods(BindingFlags.Public | BindingFlags.Instance))
  {
    if (method.Name == "SetText")
    {
      System.Windows.Forms.MessageBox.Show("Method SetText found with " + method.GetParameters().Length.ToString() + " parameters.");
    }
  }
}
catch (Exception e)
{
  System.Windows.Forms.MessageBox.Show("Error:" + Environment.NewLine + Environment.NewLine + e.Message);
}


Still no exceptions being thrown, this only shows one method as being found: "Method SetText found with 1 parameters.".

So I displayed every found method, and confirmed again that only one instance of SetText was being found.

From there, I started searching on Google, and found this on Stack Overflow, where someone suggests to use the InvokeMember function instead.

try
{
  Type t = Assembly.GetEntryAssembly().GetType("Program.TextControl"); // this is working fine
  // myInstance = exposed base interface instance, this is working fine
  t.InvokeMember("SetText", BindingFlags.InvokeMethod, Type.DefaultBinder, myInstance, new object[] { newText, false });
}
catch (Exception e)
{
  System.Windows.Forms.MessageBox.Show("Error:" + Environment.NewLine + Environment.NewLine + e.Message);
}


With this, an exception is being thrown:

Quote

---------------------------

---------------------------
Error:



Method 'Program.TextControl.SetText' not found.
---------------------------
OK
---------------------------


I have successfully reflected into other members of the same class, but I am having difficulty in finding this overload of this particular method. Other methods within the same class I am able to successfully find overloads of. If I have overlooked anything, I would appreciate a second set of eyes, though even as I've been typing this, I don't see where I have. Beyond that, if there's any reason why a particular overload of a particular method would not be able to be found by reflection, while other methods (including the other overload of the same method in the class) are able to be found, I would also appreciate that information.

Thanks in advance.

This post has been edited by monkey_05_06: 09 June 2012 - 01:39 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Reflection only finding 1 of 2 overloads.

#2 monkey_05_06  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 1
  • View blog
  • Posts: 105
  • Joined: 26-August 06

Re: Reflection only finding 1 of 2 overloads.

Posted 09 June 2012 - 02:15 PM

For the record, I have worked around this by duplicating the function code, resulting in further reflecting into several other underlying types. I would still be interested to know why the above isn't working if anyone has any insight though, so for all intents and purposes this thread isn't actually "solved" so much as I just worked around the question at hand.
Was This Post Helpful? 0
  • +
  • -

#3 Momerath  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 809
  • View blog
  • Posts: 1,949
  • Joined: 04-October 09

Re: Reflection only finding 1 of 2 overloads.

Posted 09 June 2012 - 02:21 PM

It sounds like you don't have Reflection Permission on the class.

You can probably create your assembly as a fully trusted assembly and access the method, but you'd need to do that on every machine that you run this on, and the users might not have full trust.
Was This Post Helpful? 1
  • +
  • -

#4 monkey_05_06  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 1
  • View blog
  • Posts: 105
  • Joined: 26-August 06

Re: Reflection only finding 1 of 2 overloads.

Posted 09 June 2012 - 02:26 PM

I haven't used reflection extensively, but I have read somewhat about that. As far as I can tell though, wouldn't it be all or nothing? I am able to find the one method declared immediately above the other. They have the same declared attributes (just different parameter sets) and are in the same class. So would the permissions be a likely culprit?

This post has been edited by monkey_05_06: 09 June 2012 - 02:27 PM

Was This Post Helpful? 0
  • +
  • -

#5 Momerath  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 809
  • View blog
  • Posts: 1,949
  • Joined: 04-October 09

Re: Reflection only finding 1 of 2 overloads.

Posted 09 June 2012 - 02:38 PM

I've not played with Reflection permission, so I can't speak from authority on it, but it does say you need it to access protected and private methods. From what you've posted I had assumed you were trying to access something that wasn't public (otherwise why use reflection). Were you able to see other methods that were private?
Was This Post Helpful? 0
  • +
  • -

#6 monkey_05_06  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 1
  • View blog
  • Posts: 105
  • Joined: 26-August 06

Re: Reflection only finding 1 of 2 overloads.

Posted 09 June 2012 - 02:45 PM

I'm using reflection because the class itself isn't publicly exposed to the program's extension API (it actually exists in an entirely separate assembly from the one in which the API exists). The two functions in question are public, but I don't have a way to access the class itself without either referencing the second assembly or using reflection. I chose to utilize reflection because I didn't want to have to rebuild if the other assemblies are changed (understanding of course that if the functions or their signatures are changed this would still be necessary).
Was This Post Helpful? 0
  • +
  • -

#7 Jeff H  Icon User is offline

  • D.I.C Regular

Reputation: 111
  • View blog
  • Posts: 301
  • Joined: 30-January 11

Re: Reflection only finding 1 of 2 overloads.

Posted 09 June 2012 - 05:04 PM

Is the existing program responsible for loading your 'extension'?

If so and you know for sure the second assembly you mentioned will be loaded before yours have you tried referencing the second assembley and setting 'Copy Local' to false?


So at runtime or if debugging by 'attaching to process' or 'Start external program' you can have your code compile against the assembly on your machine but at runtime use the loaded assembly loaded by the exsiting application.
Was This Post Helpful? 1
  • +
  • -

#8 monkey_05_06  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 1
  • View blog
  • Posts: 105
  • Joined: 26-August 06

Re: Reflection only finding 1 of 2 overloads.

Posted 09 June 2012 - 09:31 PM

I was not aware that such a thing was possible! :)

That definitely sounds like a better route for accessing most of the data that I'm currently reflecting into. So even if the second assembly is changed, if "Copy Local" is false, it will still link properly so long as the function signatures and so forth haven't changed? That was my biggest concern is this is an actively developed program, so the second assembly could very likely change, even just from one version of the program to the next.

And yes, the main program loads extensions directly, based on a specified extension interface that the main class of the extension DLL will inherit from (or "implement" I guess is the right term for interfaces). From there the extension can do pretty much what it wants, but again I wasn't aware that the linking could be version/revision independent.

Technically that still doesn't answer why I am able to find only 1 of 2 public overloads via reflection, but it's a very helpful and useful response (provided that I've understood you correctly). Thanks!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1