I had the need of having three different singleton remoting object in the same process.
This post explains how I solved out the trick.
I have a windows application exposing via remoting three singleton objects, let' call them "S_a", "S_b" and "S_Main" .
"S_a" and "S_b" are instantiated by remote client applications.
"S_Main" object is instantiated by "S_a" and "S_b".
"S_a", "S_b" and "S_Main" resides on the same process, as I told before.
"S_a" and "S_b" are WellKnownServiceTypes.
"S_Main" is to be both a WellKnownServiceType (this is inside the server-application code where a port is open in listening mode) and a WellKnownClientType when configuring "S_a" and "S_b" for its instantiation (i.e inside "S_a" and "S_b" class definition there will be a point in which we say that "S_Main" is not a local object and is to be instantiated via remoting at a certain URL).
Triing to configure remoting in this way, leads to the generation of the Exception:
"Remoting configuration failed with the exception System.Runtime.Remoting.RemotingException"
"Attempt to redirect activation for type" [...]
"This is not allowed since either a well-known service type has already
been registered with that type or that type has been registered has a
activated service type"
The solution is to have the three singletons in three different appdomains hosted in the same windows process.
First thing to setup is to have three assemblies every one exposing a method which will configure remoting server-side for a single singleton. The classes inside these assemblies must inherit MarshalByRefObject.
In this way instantiating these three classes and calling the method on them, will open three ports in listening mode.
Every assembly is to be loaded in a different appdomain. In this way, inside the "S_A_AppDomain" (and also in "S_B_AppDomain") the "S_Main" object is configured as a WellKnownClientType, while in the S_Main_AppDomain it is configured as a WellKnownServiceType.
AppDomains provide proper isolation.
An Appdomain is created in this way:
Dim domaininfo As New AppDomainSetup
domaininfo.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory
dim S_A_Domain As AppDomain = _
AppDomain.CreateDomain("S_A_RemotingServer", Nothing, domaininfo)
Here is the code used to load an assembly (ex: "Assembly.dll") inside the appdomain, instantiate the class (ex: "namespace.classname", which will reside in the newly created appdomain) and invoke the method that will configure remoting server-side (ex: "ActivateServer") :
Dim ann As [Assembly] = [Assembly].LoadFrom("Assembly.dll")
'Load the assembly in the appdomain
Dim a As [Assembly] = S_A_Domain.Load(ann.FullName)
'Create an instance (on the new appdomain)
Dim obj As Object = S_A_Domain.CreateInstanceAndUnwrap(ann.FullName, "namespace.classname")
'Get the type to use.
Dim myType As Type = a.GetType("namespace.classname")
'Get the method to call.
Dim mymethod As MethodInfo = myType.GetMethod("ActivateServer")
'Execute the method.
mymethod.Invoke(obj, Nothing)
The method is invoked in the instance of the class which resides in the separate appdomain, configuring remoting.
Search This Blog
Showing posts with label Remoting. Show all posts
Showing posts with label Remoting. Show all posts
Tuesday, February 24, 2009
Events between .NET Remoting wellknown objects
Suppose we have two Wellknown singleton remoting objects.
the former is instantiated by the latter, and sends events to it.
Let's call S_A and S_B the two wellknown remoting objects.
These object reside on two different appdomains. S_B is instantiated by S_A.
S_B is the source of events, and S_A has to receive them.
Note that S_A is a wellknown on his turn.
After S_B is instantiated in S_A, an exception is thrown:
Wellknown objects cannot marshal themselves in their constructor, or perform
any action that would cause themselves to be marshalled (such as passing the
this pointer as a parameter to a remote method)
The error happens at runtime, either when a handler is added for an S_B event or as soon as S_B is instantiated.
To understand why this happens, a first resume of how events works is useful.
Events are simple to use. What happens behind the curtains, is that a function is called on the target (the object handling the event -S_A-) by the sender of the event (S_B).
Since we are talking about wellknown server objects, what happens when S_B sends an event to S_A, is:
the remoting server (S_B) becomes a client of S_A (in fact S_B is calling a function on S_A) .
The exception is thrown because the wellknown object S_B is a SERVER fof S_A, so it is not allowed to use it as also as CLIENT. This is not allowed by remoting. It is allowed elsewhere.
SOLUTION :
Create a new class (C_C). Inside this class instantiate the wellknown S_B and receive his events here. S_A will instantiate C_C and receive events from it. C_C can become a client of S_A without problem since it is not a wellknown object.
the former is instantiated by the latter, and sends events to it.
Let's call S_A and S_B the two wellknown remoting objects.
These object reside on two different appdomains. S_B is instantiated by S_A.
S_B is the source of events, and S_A has to receive them.
Note that S_A is a wellknown on his turn.
After S_B is instantiated in S_A, an exception is thrown:
Wellknown objects cannot marshal themselves in their constructor, or perform
any action that would cause themselves to be marshalled (such as passing the
this pointer as a parameter to a remote method)
The error happens at runtime, either when a handler is added for an S_B event or as soon as S_B is instantiated.
To understand why this happens, a first resume of how events works is useful.
Events are simple to use. What happens behind the curtains, is that a function is called on the target (the object handling the event -S_A-) by the sender of the event (S_B).
Since we are talking about wellknown server objects, what happens when S_B sends an event to S_A, is:
the remoting server (S_B) becomes a client of S_A (in fact S_B is calling a function on S_A) .
The exception is thrown because the wellknown object S_B is a SERVER fof S_A, so it is not allowed to use it as also as CLIENT. This is not allowed by remoting. It is allowed elsewhere.
SOLUTION :
Create a new class (C_C). Inside this class instantiate the wellknown S_B and receive his events here. S_A will instantiate C_C and receive events from it. C_C can become a client of S_A without problem since it is not a wellknown object.
Subscribe to:
Posts (Atom)