Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Remoting (events/delegates)

Remoting (events/delegates)

Scheduled Pinned Locked Moved C#
questioncomgraphicssysadminhelp
11 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    leppie
    wrote on last edited by
    #1

    Hi I'll try to describe as much as possible. I have my main app running in the default appdomain. I load a plugin manager class in a new AppDomain(plugin). I pass an instance(Connection class) from my main appdomain to the "plugin" appdomain by ObjectHandle. My plugin manager class then loads the plugin assemblies. These assemblies in turn registers to some events from the Connection reference in the "plugin" appdomain. Everything (loading/unloading/events/methods/etc) functions as it should except, when registering the events in my plugin , the plugin's assembly gets loaded in the main appdomain. The question is how can i "subscribe" to these events without the main appdomian havin to load the plugin assembly? I have thought perhaps "chaining" the events to a new class in the plugin manager assembly and let my plugin subscribe to those. Seems like a lot of work (and the possiblitlity of creating duplicate/error-prone code). Damn its seems a language is sometimes too type-safe for your liking. Any input would be appreciated. I can mail you the code as well. A bit much too post. :) WebBoxes - Yet another collapsable control, but it relies on a "graphics server" for dynamic pretty rounded corners, cool arrows and unlimited font support.

    J G 2 Replies Last reply
    0
    • L leppie

      Hi I'll try to describe as much as possible. I have my main app running in the default appdomain. I load a plugin manager class in a new AppDomain(plugin). I pass an instance(Connection class) from my main appdomain to the "plugin" appdomain by ObjectHandle. My plugin manager class then loads the plugin assemblies. These assemblies in turn registers to some events from the Connection reference in the "plugin" appdomain. Everything (loading/unloading/events/methods/etc) functions as it should except, when registering the events in my plugin , the plugin's assembly gets loaded in the main appdomain. The question is how can i "subscribe" to these events without the main appdomian havin to load the plugin assembly? I have thought perhaps "chaining" the events to a new class in the plugin manager assembly and let my plugin subscribe to those. Seems like a lot of work (and the possiblitlity of creating duplicate/error-prone code). Damn its seems a language is sometimes too type-safe for your liking. Any input would be appreciated. I can mail you the code as well. A bit much too post. :) WebBoxes - Yet another collapsable control, but it relies on a "graphics server" for dynamic pretty rounded corners, cool arrows and unlimited font support.

      J Offline
      J Offline
      James T Johnson
      wrote on last edited by
      #2

      I think the recommended solution is to create a small assembly containing the portions of code to be shared between te main app and the plugins. In your case it would include the delegate definitions as well as anything else that both sides need to use. The idea is to keep this assembly small so you don't incur a large penalty for loading it twice. James "It is self repeating, of unknown pattern" Data - Star Trek: The Next Generation

      L 1 Reply Last reply
      0
      • J James T Johnson

        I think the recommended solution is to create a small assembly containing the portions of code to be shared between te main app and the plugins. In your case it would include the delegate definitions as well as anything else that both sides need to use. The idea is to keep this assembly small so you don't incur a large penalty for loading it twice. James "It is self repeating, of unknown pattern" Data - Star Trek: The Next Generation

        L Offline
        L Offline
        leppie
        wrote on last edited by
        #3

        James T. Johnson wrote: I think the recommended solution is to create a small assembly containing the portions of code to be shared between te main app and the plugins. In your case it would include the delegate definitions as well as anything else that both sides need to use. I ended up makin a "proxy" class for the object that fires these events. Basically:

        con.Listener.OnPublic += new PublicMessageEventHandler(OnPublicMessage);

        public void OnPublicMessage(UserInfo ui, string channel, string message)
        {
        if (Public != null)
        Public(ui, channel, message);
        }
        //I change the event names to be "inline" with the recommended
        public event Sharkbite.Irc.PublicMessageEventHandler Public;

        Now this work nicely, but I will be a pain in the $#% for all the events about 50, as I can see no way of get parameters for a delegate via reflection. I think i can add/remove the delegates once I have all my event raising methods in place. Maybe I can do some filtering...but there seems no way I can do the raising method programatically. The single event I have implementented works as should, and the main appdomain does NOT load the plugin's type. Thus the file is deletable once the appdomain is unloaded and it even allows me to debug, and invoke the plugin. Another idea I had was perhaps make an abstract base class that already has all the consumer methods in place that will act as a template for the plugin the pass a downcasted instance of the plugin. But again I wasnt sure ifthe main appdomain would load it. Yet another (but I have now clue on this) is to make my own implement ation of a RealProxy object. Everything seems to point to that... Anyways thanks for the help :) Cheers WebBoxes - Yet another collapsable control, but it relies on a "graphics server" for dynamic pretty rounded corners, cool arrows and unlimited font support.

        J 1 Reply Last reply
        0
        • L leppie

          James T. Johnson wrote: I think the recommended solution is to create a small assembly containing the portions of code to be shared between te main app and the plugins. In your case it would include the delegate definitions as well as anything else that both sides need to use. I ended up makin a "proxy" class for the object that fires these events. Basically:

          con.Listener.OnPublic += new PublicMessageEventHandler(OnPublicMessage);

          public void OnPublicMessage(UserInfo ui, string channel, string message)
          {
          if (Public != null)
          Public(ui, channel, message);
          }
          //I change the event names to be "inline" with the recommended
          public event Sharkbite.Irc.PublicMessageEventHandler Public;

          Now this work nicely, but I will be a pain in the $#% for all the events about 50, as I can see no way of get parameters for a delegate via reflection. I think i can add/remove the delegates once I have all my event raising methods in place. Maybe I can do some filtering...but there seems no way I can do the raising method programatically. The single event I have implementented works as should, and the main appdomain does NOT load the plugin's type. Thus the file is deletable once the appdomain is unloaded and it even allows me to debug, and invoke the plugin. Another idea I had was perhaps make an abstract base class that already has all the consumer methods in place that will act as a template for the plugin the pass a downcasted instance of the plugin. But again I wasnt sure ifthe main appdomain would load it. Yet another (but I have now clue on this) is to make my own implement ation of a RealProxy object. Everything seems to point to that... Anyways thanks for the help :) Cheers WebBoxes - Yet another collapsable control, but it relies on a "graphics server" for dynamic pretty rounded corners, cool arrows and unlimited font support.

          J Offline
          J Offline
          James T Johnson
          wrote on last edited by
          #4

          leppie wrote: Another idea I had was perhaps make an abstract base class that already has all the consumer methods in place that will act as a template for the plugin the pass a downcasted instance of the plugin. But again I wasnt sure ifthe main appdomain would load it. Just make sure that you actually do the cast instead of letting inheritance take its course. Nish and I found out while he was working on remoting that if you don't do the cast, the appdomain on the other side will try to load the assembly containing the derived class. ex

          class BaseClass
          {
          /* methods etc */
          public abstract BaseClass GetInstance();
          }

          class DerivedClass : BaseClass
          {
          public override BaseClass GetInstance()
          {
          return (BaseClass) this;
          }
          }

          if you don't perform the cast then it returns a reference to the type DerivedClass which the original appdomain doesn't know about, so it tries to load that assembly into its appdomain. In a remoting scenario where that assembly doesn't exist on the client side this results in an AssemblyNotFoundException (or whatever that exception is really called). In your plugin scenario it will either do that or it will find it and load it, nullifying the advantage of having a separate appdomain. James "It is self repeating, of unknown pattern" Data - Star Trek: The Next Generation

          L 1 Reply Last reply
          0
          • J James T Johnson

            leppie wrote: Another idea I had was perhaps make an abstract base class that already has all the consumer methods in place that will act as a template for the plugin the pass a downcasted instance of the plugin. But again I wasnt sure ifthe main appdomain would load it. Just make sure that you actually do the cast instead of letting inheritance take its course. Nish and I found out while he was working on remoting that if you don't do the cast, the appdomain on the other side will try to load the assembly containing the derived class. ex

            class BaseClass
            {
            /* methods etc */
            public abstract BaseClass GetInstance();
            }

            class DerivedClass : BaseClass
            {
            public override BaseClass GetInstance()
            {
            return (BaseClass) this;
            }
            }

            if you don't perform the cast then it returns a reference to the type DerivedClass which the original appdomain doesn't know about, so it tries to load that assembly into its appdomain. In a remoting scenario where that assembly doesn't exist on the client side this results in an AssemblyNotFoundException (or whatever that exception is really called). In your plugin scenario it will either do that or it will find it and load it, nullifying the advantage of having a separate appdomain. James "It is self repeating, of unknown pattern" Data - Star Trek: The Next Generation

            L Offline
            L Offline
            leppie
            wrote on last edited by
            #5

            Thank James I tried something like that, but it was still loading the "plugin" assembly. But I have gone the other route (a proxy class to handle events/delegates and methods). I then created an interface that it implements and pass that to the plugin, this is to prevent the plugin from having access to the public event raising methods. All in all, it works flawlessly, and mite have a nice idea for an article. :) CHeers :) WebBoxes - Yet another collapsable control, but it relies on a "graphics server" for dynamic pretty rounded corners, cool arrows and unlimited font support.

            1 Reply Last reply
            0
            • L leppie

              Hi I'll try to describe as much as possible. I have my main app running in the default appdomain. I load a plugin manager class in a new AppDomain(plugin). I pass an instance(Connection class) from my main appdomain to the "plugin" appdomain by ObjectHandle. My plugin manager class then loads the plugin assemblies. These assemblies in turn registers to some events from the Connection reference in the "plugin" appdomain. Everything (loading/unloading/events/methods/etc) functions as it should except, when registering the events in my plugin , the plugin's assembly gets loaded in the main appdomain. The question is how can i "subscribe" to these events without the main appdomian havin to load the plugin assembly? I have thought perhaps "chaining" the events to a new class in the plugin manager assembly and let my plugin subscribe to those. Seems like a lot of work (and the possiblitlity of creating duplicate/error-prone code). Damn its seems a language is sometimes too type-safe for your liking. Any input would be appreciated. I can mail you the code as well. A bit much too post. :) WebBoxes - Yet another collapsable control, but it relies on a "graphics server" for dynamic pretty rounded corners, cool arrows and unlimited font support.

              G Offline
              G Offline
              Gertjan Schuurmans
              wrote on last edited by
              #6

              Did you look into the soapsuds.exe tool? It generates empty proxy classes from your real class libraries. Gertjan Schuurmans Amsterdam

              L 3 Replies Last reply
              0
              • G Gertjan Schuurmans

                Did you look into the soapsuds.exe tool? It generates empty proxy classes from your real class libraries. Gertjan Schuurmans Amsterdam

                L Offline
                L Offline
                leppie
                wrote on last edited by
                #7

                It appears soap require webservices, and that would make it difficult (for me anyways) to incorporate a web service in a single application. If not so, I think I have been re-inventing the wheel here X|. I will definately check it out. OK, I just did, and it seems it does (the basic model) what I have done (damn why do they allways come up with MY clever ideas!!!!!). I have a couple more clever reflection tricks though :) The only other question I have is how does the object get activated? In my case the object is serverside-activated (in fact the "plugins" consume events from a persisted object). It appears that the object need to be created client side from the generated code. Thanks :) WebBoxes - Yet another collapsable control, but it relies on a "graphics server" for dynamic pretty rounded corners, cool arrows and unlimited font support.

                1 Reply Last reply
                0
                • G Gertjan Schuurmans

                  Did you look into the soapsuds.exe tool? It generates empty proxy classes from your real class libraries. Gertjan Schuurmans Amsterdam

                  L Offline
                  L Offline
                  leppie
                  wrote on last edited by
                  #8

                  After some investigation, it seems a web service maybe a quick and easy way to do a "plugin" type system. Now to figure out how to put the code together :) WebBoxes - Yet another collapsable control, but it relies on a "graphics server" for dynamic pretty rounded corners, cool arrows and unlimited font support.

                  1 Reply Last reply
                  0
                  • G Gertjan Schuurmans

                    Did you look into the soapsuds.exe tool? It generates empty proxy classes from your real class libraries. Gertjan Schuurmans Amsterdam

                    L Offline
                    L Offline
                    leppie
                    wrote on last edited by
                    #9

                    Hi there again Sorry for all the replies ;P It seems soapsuds generated classes still has the event/delegete problem (i havent tested this in a scenario yet) where the delegate gets passed into the "server" appdomain and the "plugin" would have to be serializble. Are these assumptions correct? Cheers :) WebBoxes - Yet another collapsable control, but it relies on a "graphics server" for dynamic pretty rounded corners, cool arrows and unlimited font support.

                    G 1 Reply Last reply
                    0
                    • L leppie

                      Hi there again Sorry for all the replies ;P It seems soapsuds generated classes still has the event/delegete problem (i havent tested this in a scenario yet) where the delegate gets passed into the "server" appdomain and the "plugin" would have to be serializble. Are these assumptions correct? Cheers :) WebBoxes - Yet another collapsable control, but it relies on a "graphics server" for dynamic pretty rounded corners, cool arrows and unlimited font support.

                      G Offline
                      G Offline
                      Gertjan Schuurmans
                      wrote on last edited by
                      #10

                      Hi there! Yep, I think you are stuck in a two-way dependency: you need a remotable(serializable) server for to call from within the plugin, and a serializble plugin for callback. My guess is to try to narrow this dependency down to a minimal IPlugin interface and a remotable server. hope this helps ;) Gertjan Schuurmans Amsterdam

                      L 1 Reply Last reply
                      0
                      • G Gertjan Schuurmans

                        Hi there! Yep, I think you are stuck in a two-way dependency: you need a remotable(serializable) server for to call from within the plugin, and a serializble plugin for callback. My guess is to try to narrow this dependency down to a minimal IPlugin interface and a remotable server. hope this helps ;) Gertjan Schuurmans Amsterdam

                        L Offline
                        L Offline
                        leppie
                        wrote on last edited by
                        #11

                        Gertjan Schuurmans wrote: My guess is to try to narrow this dependency down to a minimal IPlugin interface and a remotable server. I need it even simpler, no server....I just need to "proxy" the event. Thats said I have most of it working as it should, except for on problem (later on that). The way the it is as such: I have a PluginManager assembly that contains some classes, interfaces for for the handling and codegen. Then I have a UI app to select all the types required by the plugin. This UI will then do some mean CodeDom (unfortunately only C#, due to a CodeDom bug perhaps???) to generate a proxy class for each selected type and an interface for it, as well as a interface for the plugin and user class for the implementation. From there its a few lines of code to implement it. :) The problem however that im having is with AppDomainUnloadedException. I have rechecked my code x 1000 and cant see why this happens... Thanks for the help :) WebBoxes - Yet another collapsable control, but it relies on a "graphics server" for dynamic pretty rounded corners, cool arrows and unlimited font support.

                        1 Reply Last reply
                        0
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups