Why .NET Remoting does not have a RemotingConfiguration.Reset() ?
Hopefully the .NET 2.0 bits will support a similar call to reset the remoting infrastructure the clear way without restarting the whole remoting application!
As you may have noticed: there exists a RemotingChannels.UnregisterChannel() method to use to get rid of a old used channel and switch to a new one (registering). But that is not enough to get an application seamlessly work with a new remoting service endpoint: after you really used one of you configured services, you will get an exception if you try to register the service again with a different service endpoint. This is because the RemotingConfigHandler+RemotingConfigInfo method AddWellknownEntry() calls a method named CheckForRedirectedClientType() that cause a CantUseRedirectedTypeForWellKnownService exception. So after I tried a "fix" with managing the calls to the .NET remoting classes within a new separate AppDomain (and unload that on a reset remoting request) that did not work I end up with a hack using Reflection to get around that.
Here is the used code that works for our requirements:
///
/// This is cool, but it is a HACK. Please validate the code each time
/// the .NET framework gets updated. There is a little safty included to
/// throw a InvalidOperationException if something changed we require to get
/// it work somehow.
///
///
/// On every failed reflection call or if we do not get any of
/// the required FieldInfo objects
///
/// The HACK bases on the fact Remoting informations are cached
/// in the well hidden sync. Hashtable field "_remoteTypeInfo" after they get used once.
/// This field you can find within the (internal) class
/// RemotingConfigHandler.RemotingConfigInfo. The static RemotingConfigHandler.Info
/// field holds a reference to an instance if that class.
/// To reset we simply initialize that field with a new instance of
/// a synchronized Hashtable.
/// Note: We do only "fix" for Singleton objects, not client activated services.
/// So to get it "fully" work (complete state reset), you may have to hack
/// more and other fields.
///
private static void Release_NETRemotingResources() {
bool raiseError = true; // warn if we switch to a new .NET env where the reflection is maybe not working anymore!
try {
//HACK: please verify it after each Service Pack or new version of .NET runtime to be used!
Type configHandlerType = Type.GetType("System.Runtime.Remoting.RemotingConfigHandler");
if (configHandlerType != null) {
FieldInfo infoFI = configHandlerType.GetField("Info", BindingFlags.GetField | BindingFlags.Public | BindingFlags.Static);
if (infoFI != null) {
object infoFIRef = infoFI.GetValue(null); // static, so no object instance to provide
if (infoFIRef != null) {
FieldInfo remoteTypeInfoFI = infoFI.FieldType.GetField("_remoteTypeInfo", BindingFlags.Instance | BindingFlags.NonPublic);
if (remoteTypeInfoFI != null) {
remoteTypeInfoFI.SetValue(infoFIRef, Hashtable.Synchronized(new Hashtable()));
raiseError = false; // all seems to be OK
}
}
}
}
} catch (Exception ex) {
throw new InvalidOperationException("Failed to reset .NET internal remoting state.", ex);
}
if (raiseError)
throw new InvalidOperationException("Failed to reset .NET internal remoting state.");
}