For most enterprise applications, I normally suggest to use interface based access to remote objects instead of shipping the implementation assembly to the client for various reasons (versioning, deployment, ...). The drawback however is that you can't register the WellKnownObjects in a configuration file and simply use the "new" operator to instantiate references to your remote objects.
Instead, you have to resort to using Activator.GetObject() in this case. The normal behavior of this method leads to either hard coding the URL or simply using the configuration file's <appSetting> section to store the URLs there. Not the best idea, right?
The following RemotingHelper class, which has been mentioned by me on several newsgroup posts during the last months, allows you to work around this issue and simply register the interfaces as you would register any conventional wellknown object.
using System; using System.Collections; using System.Runtime.Remoting; class RemotingHelper { private static bool _isInit; private static IDictionary _wellKnownTypes; public static Object GetObject(Type type) { if (! _isInit) InitTypeCache(); WellKnownClientTypeEntry entr = (WellKnownClientTypeEntry) _wellKnownTypes[type]; if (entr == null) { throw new RemotingException("Type not found!"); } return Activator.GetObject(entr.ObjectType,entr.ObjectUrl); } public static void InitTypeCache() { _isInit = true; _wellKnownTypes= new Hashtable(); foreach (WellKnownClientTypeEntry entr in RemotingConfiguration.GetRegisteredWellKnownClientTypes()) { if (entr.ObjectType == null) { throw new RemotingException("A configured type could not " + "be found. Please check spelling"); } _wellKnownTypes.Add (entr.ObjectType,entr); } } }
Using this class, you can register interfaces in your client-side configuration file just as you would register any wellknown object. Let's assume you have the following interface in an assembly called MyInterfaces.DLL:
public interface IFooBar { void Baz(); }
You can then create a client side configuration file like this
<configuration> <system.runtime.remoting> <application> <channels> <channel ref="http" /> </channels> <client> <wellknown type="IFooBar, MyInterfaces" url="http://localhost:5555/FooBar.soap" /> </client> </application> </system.runtime.remoting> </configuration>
With this configuration file and the RemotingHelper shown above, you can use the following code on your client to acquire an interface based remote reference without hardcoding the URL:
using System; using System.Runtime.Remoting; class Client { static void Main(string[] args) { String filename = "client.exe.config"; RemotingConfiguration.Configure(filename); IFooBar obj = (IFooBar) RemotingHelper.GetObject(typeof(IFooBar)); Console.WriteLine("Done..."); } }