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.
No comments:
Post a Comment