0

I have a program called Scenario2_Client.xaml.cs that has the following function:

namespace SDKTemplate
{

    public sealed partial class Scenario2_Client : Page
    {
        private MainPage rootPage = MainPage.Current;
        // code

        // this is the function I would like to call
        private void RemoveValueChangedHandler() 
        {
            ValueChangedSubscribeToggle.Content = "Subscribe to value changes";
            if (subscribedForNotifications)
            {
                registeredCharacteristic.ValueChanged -= Characteristic_ValueChanged;
                registeredCharacteristic = null;
                subscribedForNotifications = false;
            }
        }
        // ...
    }
}

And then I have added a class in a different file (but in the same project) called EchoClient.cs which has the following code:

namespace SDKTemplate
{
     class EchoClient
     {
         public void TcpClient()
         {
             try
             {
                 TcpClient client = new TcpClient("139.169.63.130", 9999);
                 StreamReader reader = new StreamReader(client.GetStream());
                 StreamWriter writer = new StreamWriter(client.GetStream());
                 string s = string.Empty;
                 while (!s.Equals("Exit"))
                 {
                     Console.WriteLine("TCP Client connected....");
                     Console.WriteLine("Enter a string or number to send to the server: ");
                     s = Console.ReadLine();                    
                     writer.WriteLine(s);
                     writer.Flush();
                     string server_string = reader.ReadLine();
                     Console.WriteLine(server_string);
                 }

                 reader.Dispose();
                 writer.Dispose();
                 client.Dispose();

             }
             catch (Exception e)
             {
                 Console.WriteLine(e);
             }
         }
     }


    internal class Console
    {
        internal static string ReadLine()
        {
            throw new NotImplementedException();
        }

        internal static void WriteLine(string v)
        {
            throw new NotImplementedException();
        }

        internal static void WriteLine(Exception e)
        {
            throw new NotImplementedException();
        }


    internal class TcpClient
    {
        private string v1;
        private int v2;

        public TcpClient(string v1, int v2)
        {
            this.v1 = v1;
            this.v2 = v2;
        }

        internal void Dispose()
        {
            throw new NotImplementedException();
        }

        internal Stream GetStream()
        {
            throw new NotImplementedException();
        }
    }    
 }

Is there a way to call that function from this class?

I would have done something like this if it was public:

EchoClient client = new EchoClient()
client.somefunction();
client.somefunction();

..but since this method is private, how should I access it?

trashr0x
  • 6,457
  • 2
  • 29
  • 39
Smit Modi
  • 55
  • 3
  • 13
  • 12
    If you need to access it outside, why is it private in the first place? – Broots Waymb Oct 09 '18 at 14:32
  • 3
    Reflection or change access modifier. – Renatas M. Oct 09 '18 at 14:35
  • @ Broots Waymb Well, I did not make that private. Scenario2 is an example straight from Microsoft on git. – Smit Modi Oct 09 '18 at 14:35
  • 2
    There is probably a good reason why Microsoft made that method private. – Polyfun Oct 09 '18 at 14:40
  • If you have enough permissions you can reflect on the type, get the private functions and invoke it. However, generally, private functions are designed not to be called from the outside. – Flydog57 Oct 09 '18 at 14:41
  • 1
    To ask stereotypical message board questions: _Why would you like to do so? What do you want to achieve?_ That being said, a private method can be invoked using reflection. – Codor Oct 09 '18 at 14:42
  • @ Codor Okay let me be more precise here. So compiling Scenario 2 program gives me this data (mark in yellow and red) https://ibb.co/m2tqrp However, I am trying to get those data on TCP Server. This is why I wrote TCP Client code. – Smit Modi Oct 09 '18 at 14:45
  • And you want to unsubscribe the handler...why don't you write identical lets say Scenario2_TCP_Client page, copy relevant code from original Scenario2_Client and add your TCP client code? Because it looks like you doing something strange :) – Renatas M. Oct 09 '18 at 14:54
  • Yeah that is one way to do that. I was just thinking maybe there is a faster way to accomplish this. – Smit Modi Oct 09 '18 at 15:02
  • @SmitModi where did you find such code? `Microsoft on Git` probably means on Github, where you'll find either *samples* that you can modify or *framework code* that you shouldn't. There's no reason to try to access private methods in framework libraries – Panagiotis Kanavos Oct 09 '18 at 15:13

2 Answers2

3

It is possible to invoke a private method using reflection as follows.

var iMethod
  = client.GetType().GetMethod("somefunction",
                               BindingFlags.NonPublic | BindingFlags.Instance);
iMethod.Invoke(client, new object[]{});
Codor
  • 17,447
  • 9
  • 29
  • 56
2

I'm not sure why @Codor was down-voted, but here's the same answer fleshed out a little more. First I create a class with a private method:

public class PrivateFunction
{
    private int _age;

    public PrivateFunction(int age)
    {
        _age = age;
    }

    private int DoSomethingPrivate(string parameter)
    {
        Debug.WriteLine($"Parameter: {parameter}, Age: {_age}");
        return _age;
    }
}

I created a method that takes parameters and returns an integer to show all possibilities.

Then I call it:

   var type = typeof(PrivateFunction);
   var func = type.GetMethod("DoSomethingPrivate", BindingFlags.Instance | BindingFlags.NonPublic);
   var obj = new PrivateFunction(12);
   var ret = func.Invoke(obj, new[] {"some parameter"});
   Debug.WriteLine($"Function returned {ret}");

and I get this in the output (proving something happened):

Parameter: some parameter, Age: 12
Function returned 12

If you are going to repeatedly call the same function (perhaps with different objects), save the MethodInfo object in func. It's immutable and re-useable.

Flydog57
  • 6,851
  • 2
  • 17
  • 18
  • Hmmm... Someone doesn't like using Reflection to call private methods. Why the downvote on this answer and on @Codor 's. This directly answers the question "Calling a private function from another class in C#". As far as I know, it's the only way to answer it. Perhaps someone has a philosophical objection to doing this? – Flydog57 Oct 09 '18 at 15:12
  • came across to this video:[ https://www.youtube.com/watch?v=JztHEM7Wm3c ] he is accessing private methods outside the class using reflection and got down voted. – Smit Modi Oct 09 '18 at 15:16
  • It's generally not advisable to do this. You are breaking the original developer's assumptions, and so you are marching off into untested waters. However, sometimes you need to do it. Using reflection (similar to what @Codor and I have posted) is the way to do it. – Flydog57 Oct 09 '18 at 15:18
  • Thank you for your answer. but How do I follow this to use it in my problem? For example let's say scenario 2 is my private function and then I go to EchoClient class and call the method like you mentioned ? – Smit Modi Oct 09 '18 at 15:28
  • My `PrivateFunction` class corresponds to your `Scenario2_Client` class. My `DoSomethingPrivate` method corresponds with your `RemoveValueChangedHandler` method (i.e., the private method you want to call). Wherever you want to call it, get the type of `Scenario2_Client`, then get the `MethodInfo` corresponding to `RemoveValueChangedHandler` (using `GetMethod`) and `Invoke` it. – Flydog57 Oct 09 '18 at 15:33
  • and how about EchoClient.cs class? Could you please explain that as well? – Smit Modi Oct 09 '18 at 15:40
  • Sorry, I don't understand what you want me to explain. You wanted to call a private method of some class (and I showed you how). What does " EchoClient.cs class" have to do with it? By the way, throwing a `NotImplementedException` from a Dispose method will cause you grief. I'm not sure why it's there (since it doesn't look like you implement `IDisposable`). But, it's just weird – Flydog57 Oct 09 '18 at 16:30
  • Okay let me be more precise here. So compiling Scenario 2 program gives me this data (mark in yellow and red) [https://ibb.co/m2tqrp] However, I am trying to get those data on TCP Server. This is why I have EchoClient or TcpClient whatever you call it. I wanted to call that method from the EchoClient class. – Smit Modi Oct 09 '18 at 16:51
  • I get a 404 on that link ("That page doesn't exist"). If you want to call a private function, do what I show, get the `Type` of the class that contains the function, call `GetMethod` on that type, passing in the name of the function and the OR of those two `BindingFlags`. That will return a `MethodInfo`. Then call `Invoke` on that `MethodInfo`, passing an instance of the class to which the private method belongs. _It Should Just Work_ – Flydog57 Oct 09 '18 at 18:06
  • I don't know. Your image shows a display from your application. I'm not sure what you want. Have you tried calling the function you are interested in calling in the way I have described. That is how you call a private function from another class. Give it a try – Flydog57 Oct 09 '18 at 18:15
  • Hey so I tried but it's not working. I think it's a different thing when you have a Page. One you showed me is just a console app if I am not wrong. – Smit Modi Oct 10 '18 at 18:49
  • Code is code. It's not a web app nor a console app. I just glommed it onto a test app I had open (hence the use of `Debug.WriteLine` which uses the debug console and not a real console). Edit your question and put "Update" (with an underline) and say you took the answers, wrote this code (show your code) and it's not working (and explain what "not working" means). One thing to note is that if you are running a web app you may not have enough permissions to Reflect over private members (that's a privileged operation). In that case, -too bad-. – Flydog57 Oct 10 '18 at 18:58
  • Okay. So instead of calling private method I used a different technique. here is the question I have asked. Can you help me with that? Link: https://stackoverflow.com/questions/52819073/get-the-live-data-on-tcp-server-from-uwp – Smit Modi Oct 16 '18 at 20:07