Assign method to private delegate without breaking the current assignment












0















I'd like to use private delegate from some class, but without breaking the current assignment.
Can I somehow ensure that my changes (done by reflection) do not disconnect WriteToDebug?



Delegate is private and "Inform" is private



public class ExternalClass
{
private delegate void InformDelegate(string info);//PRIVATE!
private InformDelegate Inform { get; set; }//PRIVATE!

public ExternalClass()
{
Inform = WriteToDebug;//Default method
}

public void Foo(string bar)
{
Inform?.Invoke(bar);
}

private void WriteToDebug(string info)
{
Debug.WriteLine($"Info: {info}");
}
}


Adding my method to the delegate and some test (Debug.WriteLine + MessageBox.Show are required)



public class MyClass
{
public void Test(string message)
{
ExternalClass externalClass = new ExternalClass();
externalClass.Foo(message);

//Assign MyMethod to SomeClass.Inform
MethodInfo mi = GetType().GetMethod(nameof(MyMethod), BindingFlags.NonPublic | BindingFlags.Instance);
PropertyInfo pi = externalClass.GetType().GetProperty("Inform", BindingFlags.NonPublic | BindingFlags.Instance);
object del = Delegate.CreateDelegate(pi.PropertyType, this, mi);
Type type = externalClass.GetType().GetNestedType("Inform", BindingFlags.Public | BindingFlags.NonPublic);
pi.SetValue(externalClass, del);

//Try Foo again
externalClass.Foo(message);//TODO: Ensure that the call "Inform? .Invoke (bar);" triggered both methods: WriteToDebug and MyMethod.
}

private void MyMethod(string msg)
{
MessageBox.Show(msg);
}
}


Verification



internal class Program
{
private static void Main(string args)
{
MyClass myClass = new MyClass();
myClass.Test("Hello Word!");

Console.ReadKey();
}
}


I will be grateful for your help










share|improve this question



























    0















    I'd like to use private delegate from some class, but without breaking the current assignment.
    Can I somehow ensure that my changes (done by reflection) do not disconnect WriteToDebug?



    Delegate is private and "Inform" is private



    public class ExternalClass
    {
    private delegate void InformDelegate(string info);//PRIVATE!
    private InformDelegate Inform { get; set; }//PRIVATE!

    public ExternalClass()
    {
    Inform = WriteToDebug;//Default method
    }

    public void Foo(string bar)
    {
    Inform?.Invoke(bar);
    }

    private void WriteToDebug(string info)
    {
    Debug.WriteLine($"Info: {info}");
    }
    }


    Adding my method to the delegate and some test (Debug.WriteLine + MessageBox.Show are required)



    public class MyClass
    {
    public void Test(string message)
    {
    ExternalClass externalClass = new ExternalClass();
    externalClass.Foo(message);

    //Assign MyMethod to SomeClass.Inform
    MethodInfo mi = GetType().GetMethod(nameof(MyMethod), BindingFlags.NonPublic | BindingFlags.Instance);
    PropertyInfo pi = externalClass.GetType().GetProperty("Inform", BindingFlags.NonPublic | BindingFlags.Instance);
    object del = Delegate.CreateDelegate(pi.PropertyType, this, mi);
    Type type = externalClass.GetType().GetNestedType("Inform", BindingFlags.Public | BindingFlags.NonPublic);
    pi.SetValue(externalClass, del);

    //Try Foo again
    externalClass.Foo(message);//TODO: Ensure that the call "Inform? .Invoke (bar);" triggered both methods: WriteToDebug and MyMethod.
    }

    private void MyMethod(string msg)
    {
    MessageBox.Show(msg);
    }
    }


    Verification



    internal class Program
    {
    private static void Main(string args)
    {
    MyClass myClass = new MyClass();
    myClass.Test("Hello Word!");

    Console.ReadKey();
    }
    }


    I will be grateful for your help










    share|improve this question

























      0












      0








      0








      I'd like to use private delegate from some class, but without breaking the current assignment.
      Can I somehow ensure that my changes (done by reflection) do not disconnect WriteToDebug?



      Delegate is private and "Inform" is private



      public class ExternalClass
      {
      private delegate void InformDelegate(string info);//PRIVATE!
      private InformDelegate Inform { get; set; }//PRIVATE!

      public ExternalClass()
      {
      Inform = WriteToDebug;//Default method
      }

      public void Foo(string bar)
      {
      Inform?.Invoke(bar);
      }

      private void WriteToDebug(string info)
      {
      Debug.WriteLine($"Info: {info}");
      }
      }


      Adding my method to the delegate and some test (Debug.WriteLine + MessageBox.Show are required)



      public class MyClass
      {
      public void Test(string message)
      {
      ExternalClass externalClass = new ExternalClass();
      externalClass.Foo(message);

      //Assign MyMethod to SomeClass.Inform
      MethodInfo mi = GetType().GetMethod(nameof(MyMethod), BindingFlags.NonPublic | BindingFlags.Instance);
      PropertyInfo pi = externalClass.GetType().GetProperty("Inform", BindingFlags.NonPublic | BindingFlags.Instance);
      object del = Delegate.CreateDelegate(pi.PropertyType, this, mi);
      Type type = externalClass.GetType().GetNestedType("Inform", BindingFlags.Public | BindingFlags.NonPublic);
      pi.SetValue(externalClass, del);

      //Try Foo again
      externalClass.Foo(message);//TODO: Ensure that the call "Inform? .Invoke (bar);" triggered both methods: WriteToDebug and MyMethod.
      }

      private void MyMethod(string msg)
      {
      MessageBox.Show(msg);
      }
      }


      Verification



      internal class Program
      {
      private static void Main(string args)
      {
      MyClass myClass = new MyClass();
      myClass.Test("Hello Word!");

      Console.ReadKey();
      }
      }


      I will be grateful for your help










      share|improve this question














      I'd like to use private delegate from some class, but without breaking the current assignment.
      Can I somehow ensure that my changes (done by reflection) do not disconnect WriteToDebug?



      Delegate is private and "Inform" is private



      public class ExternalClass
      {
      private delegate void InformDelegate(string info);//PRIVATE!
      private InformDelegate Inform { get; set; }//PRIVATE!

      public ExternalClass()
      {
      Inform = WriteToDebug;//Default method
      }

      public void Foo(string bar)
      {
      Inform?.Invoke(bar);
      }

      private void WriteToDebug(string info)
      {
      Debug.WriteLine($"Info: {info}");
      }
      }


      Adding my method to the delegate and some test (Debug.WriteLine + MessageBox.Show are required)



      public class MyClass
      {
      public void Test(string message)
      {
      ExternalClass externalClass = new ExternalClass();
      externalClass.Foo(message);

      //Assign MyMethod to SomeClass.Inform
      MethodInfo mi = GetType().GetMethod(nameof(MyMethod), BindingFlags.NonPublic | BindingFlags.Instance);
      PropertyInfo pi = externalClass.GetType().GetProperty("Inform", BindingFlags.NonPublic | BindingFlags.Instance);
      object del = Delegate.CreateDelegate(pi.PropertyType, this, mi);
      Type type = externalClass.GetType().GetNestedType("Inform", BindingFlags.Public | BindingFlags.NonPublic);
      pi.SetValue(externalClass, del);

      //Try Foo again
      externalClass.Foo(message);//TODO: Ensure that the call "Inform? .Invoke (bar);" triggered both methods: WriteToDebug and MyMethod.
      }

      private void MyMethod(string msg)
      {
      MessageBox.Show(msg);
      }
      }


      Verification



      internal class Program
      {
      private static void Main(string args)
      {
      MyClass myClass = new MyClass();
      myClass.Test("Hello Word!");

      Console.ReadKey();
      }
      }


      I will be grateful for your help







      c# delegates system.reflection propertyinfo methodinfo






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 21 '18 at 20:28









      g_mg_m

      516




      516
























          1 Answer
          1






          active

          oldest

          votes


















          2














          You have to combine your delegate with the existing one (here: pointing to WriteToDebug) via Delegate.Combine.



          Retrieve this already existing one via:



          Delegate original = pi.GetValue(externalClass) as Delegate;


          and combine your new one via:



          Delegate combined = Delegate.Combine(original, del);


          Note that the order of the passed in delegates represents the order of execution.



          Your full code from above will look like below.



          ExternalClass externalClass = new ExternalClass();

          MethodInfo mi = GetType().GetMethod(nameof(MyMethod), BindingFlags.NonPublic | BindingFlags.Instance);
          PropertyInfo pi = externalClass.GetType().GetProperty("Inform", BindingFlags.NonPublic | BindingFlags.Instance);

          Delegate del = Delegate.CreateDelegate(pi.PropertyType, this, mi);

          Delegate original = pi.GetValue(externalClass) as Delegate;
          Delegate combined = Delegate.Combine(original, del);

          pi.SetValue(externalClass, combined);

          externalClass.Foo(message);





          share|improve this answer


























          • Yes, excellent! It works even if Inform == null. Thank you very much @pfx

            – g_m
            Nov 22 '18 at 5:45











          • Do you know how to extend it so that you can pass an additional parameter to the MyMethod method (a parameter that is not present in the original delegate, but is known during the execution of Delegate.Combine). So Inform will still call WriteToDebug (string info), but also MyMethod (string msg, string EXTRA_PARAMETER). EXTRA_PARAMETER will be served somewhere in the code that @pfx proposed. But where and how to do it?

            – g_m
            Nov 23 '18 at 14:49











          • EXTRA_PARAMETER can be transferred when the appropriate overload is used: docs.microsoft.com/en-us/dotnet/api/…

            – g_m
            Dec 3 '18 at 11:03











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53420013%2fassign-method-to-private-delegate-without-breaking-the-current-assignment%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2














          You have to combine your delegate with the existing one (here: pointing to WriteToDebug) via Delegate.Combine.



          Retrieve this already existing one via:



          Delegate original = pi.GetValue(externalClass) as Delegate;


          and combine your new one via:



          Delegate combined = Delegate.Combine(original, del);


          Note that the order of the passed in delegates represents the order of execution.



          Your full code from above will look like below.



          ExternalClass externalClass = new ExternalClass();

          MethodInfo mi = GetType().GetMethod(nameof(MyMethod), BindingFlags.NonPublic | BindingFlags.Instance);
          PropertyInfo pi = externalClass.GetType().GetProperty("Inform", BindingFlags.NonPublic | BindingFlags.Instance);

          Delegate del = Delegate.CreateDelegate(pi.PropertyType, this, mi);

          Delegate original = pi.GetValue(externalClass) as Delegate;
          Delegate combined = Delegate.Combine(original, del);

          pi.SetValue(externalClass, combined);

          externalClass.Foo(message);





          share|improve this answer


























          • Yes, excellent! It works even if Inform == null. Thank you very much @pfx

            – g_m
            Nov 22 '18 at 5:45











          • Do you know how to extend it so that you can pass an additional parameter to the MyMethod method (a parameter that is not present in the original delegate, but is known during the execution of Delegate.Combine). So Inform will still call WriteToDebug (string info), but also MyMethod (string msg, string EXTRA_PARAMETER). EXTRA_PARAMETER will be served somewhere in the code that @pfx proposed. But where and how to do it?

            – g_m
            Nov 23 '18 at 14:49











          • EXTRA_PARAMETER can be transferred when the appropriate overload is used: docs.microsoft.com/en-us/dotnet/api/…

            – g_m
            Dec 3 '18 at 11:03
















          2














          You have to combine your delegate with the existing one (here: pointing to WriteToDebug) via Delegate.Combine.



          Retrieve this already existing one via:



          Delegate original = pi.GetValue(externalClass) as Delegate;


          and combine your new one via:



          Delegate combined = Delegate.Combine(original, del);


          Note that the order of the passed in delegates represents the order of execution.



          Your full code from above will look like below.



          ExternalClass externalClass = new ExternalClass();

          MethodInfo mi = GetType().GetMethod(nameof(MyMethod), BindingFlags.NonPublic | BindingFlags.Instance);
          PropertyInfo pi = externalClass.GetType().GetProperty("Inform", BindingFlags.NonPublic | BindingFlags.Instance);

          Delegate del = Delegate.CreateDelegate(pi.PropertyType, this, mi);

          Delegate original = pi.GetValue(externalClass) as Delegate;
          Delegate combined = Delegate.Combine(original, del);

          pi.SetValue(externalClass, combined);

          externalClass.Foo(message);





          share|improve this answer


























          • Yes, excellent! It works even if Inform == null. Thank you very much @pfx

            – g_m
            Nov 22 '18 at 5:45











          • Do you know how to extend it so that you can pass an additional parameter to the MyMethod method (a parameter that is not present in the original delegate, but is known during the execution of Delegate.Combine). So Inform will still call WriteToDebug (string info), but also MyMethod (string msg, string EXTRA_PARAMETER). EXTRA_PARAMETER will be served somewhere in the code that @pfx proposed. But where and how to do it?

            – g_m
            Nov 23 '18 at 14:49











          • EXTRA_PARAMETER can be transferred when the appropriate overload is used: docs.microsoft.com/en-us/dotnet/api/…

            – g_m
            Dec 3 '18 at 11:03














          2












          2








          2







          You have to combine your delegate with the existing one (here: pointing to WriteToDebug) via Delegate.Combine.



          Retrieve this already existing one via:



          Delegate original = pi.GetValue(externalClass) as Delegate;


          and combine your new one via:



          Delegate combined = Delegate.Combine(original, del);


          Note that the order of the passed in delegates represents the order of execution.



          Your full code from above will look like below.



          ExternalClass externalClass = new ExternalClass();

          MethodInfo mi = GetType().GetMethod(nameof(MyMethod), BindingFlags.NonPublic | BindingFlags.Instance);
          PropertyInfo pi = externalClass.GetType().GetProperty("Inform", BindingFlags.NonPublic | BindingFlags.Instance);

          Delegate del = Delegate.CreateDelegate(pi.PropertyType, this, mi);

          Delegate original = pi.GetValue(externalClass) as Delegate;
          Delegate combined = Delegate.Combine(original, del);

          pi.SetValue(externalClass, combined);

          externalClass.Foo(message);





          share|improve this answer















          You have to combine your delegate with the existing one (here: pointing to WriteToDebug) via Delegate.Combine.



          Retrieve this already existing one via:



          Delegate original = pi.GetValue(externalClass) as Delegate;


          and combine your new one via:



          Delegate combined = Delegate.Combine(original, del);


          Note that the order of the passed in delegates represents the order of execution.



          Your full code from above will look like below.



          ExternalClass externalClass = new ExternalClass();

          MethodInfo mi = GetType().GetMethod(nameof(MyMethod), BindingFlags.NonPublic | BindingFlags.Instance);
          PropertyInfo pi = externalClass.GetType().GetProperty("Inform", BindingFlags.NonPublic | BindingFlags.Instance);

          Delegate del = Delegate.CreateDelegate(pi.PropertyType, this, mi);

          Delegate original = pi.GetValue(externalClass) as Delegate;
          Delegate combined = Delegate.Combine(original, del);

          pi.SetValue(externalClass, combined);

          externalClass.Foo(message);






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 22 '18 at 7:50

























          answered Nov 21 '18 at 21:37









          pfxpfx

          5,240121934




          5,240121934













          • Yes, excellent! It works even if Inform == null. Thank you very much @pfx

            – g_m
            Nov 22 '18 at 5:45











          • Do you know how to extend it so that you can pass an additional parameter to the MyMethod method (a parameter that is not present in the original delegate, but is known during the execution of Delegate.Combine). So Inform will still call WriteToDebug (string info), but also MyMethod (string msg, string EXTRA_PARAMETER). EXTRA_PARAMETER will be served somewhere in the code that @pfx proposed. But where and how to do it?

            – g_m
            Nov 23 '18 at 14:49











          • EXTRA_PARAMETER can be transferred when the appropriate overload is used: docs.microsoft.com/en-us/dotnet/api/…

            – g_m
            Dec 3 '18 at 11:03



















          • Yes, excellent! It works even if Inform == null. Thank you very much @pfx

            – g_m
            Nov 22 '18 at 5:45











          • Do you know how to extend it so that you can pass an additional parameter to the MyMethod method (a parameter that is not present in the original delegate, but is known during the execution of Delegate.Combine). So Inform will still call WriteToDebug (string info), but also MyMethod (string msg, string EXTRA_PARAMETER). EXTRA_PARAMETER will be served somewhere in the code that @pfx proposed. But where and how to do it?

            – g_m
            Nov 23 '18 at 14:49











          • EXTRA_PARAMETER can be transferred when the appropriate overload is used: docs.microsoft.com/en-us/dotnet/api/…

            – g_m
            Dec 3 '18 at 11:03

















          Yes, excellent! It works even if Inform == null. Thank you very much @pfx

          – g_m
          Nov 22 '18 at 5:45





          Yes, excellent! It works even if Inform == null. Thank you very much @pfx

          – g_m
          Nov 22 '18 at 5:45













          Do you know how to extend it so that you can pass an additional parameter to the MyMethod method (a parameter that is not present in the original delegate, but is known during the execution of Delegate.Combine). So Inform will still call WriteToDebug (string info), but also MyMethod (string msg, string EXTRA_PARAMETER). EXTRA_PARAMETER will be served somewhere in the code that @pfx proposed. But where and how to do it?

          – g_m
          Nov 23 '18 at 14:49





          Do you know how to extend it so that you can pass an additional parameter to the MyMethod method (a parameter that is not present in the original delegate, but is known during the execution of Delegate.Combine). So Inform will still call WriteToDebug (string info), but also MyMethod (string msg, string EXTRA_PARAMETER). EXTRA_PARAMETER will be served somewhere in the code that @pfx proposed. But where and how to do it?

          – g_m
          Nov 23 '18 at 14:49













          EXTRA_PARAMETER can be transferred when the appropriate overload is used: docs.microsoft.com/en-us/dotnet/api/…

          – g_m
          Dec 3 '18 at 11:03





          EXTRA_PARAMETER can be transferred when the appropriate overload is used: docs.microsoft.com/en-us/dotnet/api/…

          – g_m
          Dec 3 '18 at 11:03




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53420013%2fassign-method-to-private-delegate-without-breaking-the-current-assignment%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

          Alcedinidae

          RAC Tourist Trophy