programming4us
programming4us
ENTERPRISE

Programming .NET Components : Building a Distributed Application (part 3) - Programmatic Configuration Example, Administrative Configuration

9/29/2012 2:01:45 AM

3. Programmatic Configuration Example

Instead of fragmented code samples, it's now time for a more comprehensive example showing how the different steps required for programmatic configuration fit together, on both the client and the host side. As mentioned previously, since both the host and the client require the server's metadata, it's best if the server is in a class library. The constructor brings up a message box so that you can tell when a new object is created, which is especially useful when experimenting with single-call or singleton objects. The single public method of MyClass is Count( ), which pops up a message box showing the incremented value of a counter. The counter indicates the state lifecycle in the different activation modes. The message boxes have as their captions the name of the current app domain. The RemoteServerHost application is a dialog-based application. Its Main( ) method registers TCP, IPC, and HTTP channels and then displays the dialog shown in Figure 1.

Displaying a form by calling Application.Run( ) is a blocking operation, and control returns to the Main( ) method only when the dialog is closed. This, of course, has no effect on the channels registered, because worker threads are used to monitor the channels. When the dialog is closed, the Main( ) method unregisters the channels and exits. The Server Host dialog lets you check how the host registers the MyClass type it exports: as client-activated, server-activated, or both. If you select Server Activated, you

Figure 1. Server Host lets you programmatically decide which activation modes to register

need to choose between Single Call and Singleton, using the radio buttons. When you click the Register Object button, the OnRegister( ) method is called . OnRegister( ) simply registers the object based on the user-interface selections. Note that you can register the object both as client- and server-activated.

The Client application displays the dialog shown in Figure 2. You can select either Client Activated or Server Activated (but not both), and then register the type with the OnRegister( ) method. The interesting part of the client application is the way it constructs the activation URL for the object registration. The helper method GetActivationURL( ) constructs a URL based on the channel selected (starts with tcp://, http://, or ipc://) and appends the URI only if Server Activated mode is selected. OnRegister( ) calls GetActivationURL( ) and then registers the type accordingly. When you click "new" in the Client of Remote Object dialog, it simply uses new to create a new instance of MyClass and calls Count( ) twice, either remotely (if you registered) or locally (if no registration took place).

Figure 2. Client lets you choose a channel and an activation mode


Example 1. Programmatic remoting configuration
/////////////////////   ServerAssembly class library  ////////////////////////////
namespace RemoteServer
{
   public class MyClass : MarshalByRefObject
   {
      int m_Counter = 0;
      public MyClass( )
      {
         string appName = AppDomain.CurrentDomain.FriendlyName;
         MessageBox.Show("Constructor",appName);
      }
      public void Count( )
      {
         m_Counter++;
         string appName = AppDomain.CurrentDomain.FriendlyName;
         MessageBox.Show("Counter value is " + m_Counter,appName);
      }
   }
}
//////////////////////  RemoteServerHost EXE assembly  ///////////////////////////
using RemoteServer;
  
partial class ServerHostDialog : Form
{
   Button RegisterButton;
   RadioButton m_SingletonRadio;
   RadioButton m_SingleCallRadio;
   CheckBox m_ClientActivatedCheckBox;
   CheckBox m_ServerActivatedCheckBox;
   GroupBox m_GroupActivationMode;
  
   public ServerHostDialog( )
   {
      InitializeComponent( );
   }
   void InitializeComponent( )
   {...}
  
   static void Main( )
   {
      //Registering TCP channel
      IChannel tcpChannel = new TcpChannel(8005);
      ChannelServices.RegisterChannel(tcpChannel);
  
      //Registering http channel
      IChannel httpChannel = new HttpChannel(8006);
      ChannelServices.RegisterChannel(httpChannel);
           
      //Registering IPC channel
      IChannel ipcChannel = new IpcChannel("MyHost");
      ChannelServices.RegisterChannel(ipcChannel);

      Application.Run(new ServerHostDialog( ));
  
      //Do not have to, but cleaner:
      ChannelServices.UnregisterChannel(tcpChannel);
      ChannelServices.UnregisterChannel(httpChannel);
      ChannelServices.UnregisterChannel(ipcChannel);
   }
   void OnRegister(object sender,EventArgs e)
   {
      Type serverType = typeof(MyClass);
  
      //if the client activated checkbox is checked:
      if(m_ClientActivatedCheckBox.Checked)
      {
         RemotingConfiguration.RegisterActivatedServiceType(serverType);
      }
  
      //if the server activated checkbox is checked:
      if(m_ServerActivatedCheckBox.Checked)
      {
         if(m_SingleCallRadio.Checked)
         {
            //Allow Server activation, single call mode:
            RemotingConfiguration.RegisterWellKnownServiceType(serverType,
                                                               "MyRemoteServer",
                                                  WellKnownObjectMode.SingleCall);
            }
            else
            {
               //Allow Server activation, singleton mode:
               RemotingConfiguration.RegisterWellKnownServiceType(serverType,
                                                                 "MyRemoteServer",
                                                   WellKnownObjectMode.Singleton);
            }
         }
      }
   }
}
//////////////////////////  Client EXE assembly  /////////////////////////////////
using RemoteServer;
  
partial class ClientForm : Form
{
   RadioButton m_HttpRadio;
   RadioButton m_TCPRadio;
   RadioButton m_ServerRadio;
   RadioButton m_ClientRadio;
   GroupBox m_ChannelGroup;
   GroupBox m_ActivationGroup;
   Button m_NewButton;
   Button m_RegisterButton;
  
   public ClientForm( )
   {
      InitializeComponent( );
   }
   void InitializeComponent( )
   {...}
   static void Main( )
   {
      Application.Run(new ClientForm( ));
   }
   string GetActivationURL( )
   {
      if(m_TCPRadio.Checked)
      {
         if(m_ServerRadio.Checked)
         {
            //Server activation over TCP. Note object URI
            return "tcp://localhost:8005/MyRemoteServer";
         }
         else
         {
            //Client activation over TCP
            return "tcp://localhost:8005";
         }
      }
      if(m_HttpRadio.Checked)//http channel
      {
         if(m_ServerRadio.Checked)
         {
            //Server activation over http. Note object URI
            return "http://localhost:8006/MyRemoteServer";
         }
         else
         {
            //Client activation over http
            return "http://localhost:8006";
         }
      }
      else//IPC channel
      {
         if(m_ServerRadio.Checked)
         {
            //Server activation over IPC. Note object URI
            return "ipc://MyHost/MyRemoteServer";
         }
         else
         {
            //Client activation over IPC
            return "ipc://MyHost";
         }
      }
   }
   void OnRegister(object sender,EventArgs e)
   {
      Type serverType = typeof(MyClass);
      string url = GetActivationURL( );
  
      if(m_ServerRadio.Checked)
      {
         RemotingConfiguration.RegisterWellKnownClientType(serverType,url);
      }
      else //Client activation mode
      {
         //Register just once:
         RemotingConfiguration.RegisterActivatedClientType(serverType,url);
      }
   }
   void OnNew(object sender,EventArgs e)
   {
      MyClass obj;
      obj = new MyClass( );
      obj.Count( );
      obj.Count( );
   }
}


					  

4. Administrative Configuration

Both client and host applications can take advantage of a configuration file to specify their remoting settings instead of making programmatic calls. Although you can use whatever name you want for the configuration file, the convention is to give it the same name as the application, but suffixed with .config, like so: <app name>.exe.config. For example, if the host assembly is called RemoteServerHost.exe, the configuration file will be called RemoteServerHost.exe.config. The configuration file is an XML file, and it can be the same configuration file that captures custom version-binding policies. You'll find the remoting configuration section in the <application> tag, under the <system.runtime.remoting> tag:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
       <system.runtime.remoting>
          <application>
                <!--Remoting configuration setting goes here -->
          </application>
       </system.runtime.remoting>
    </configuration>

Both the client and the host load the configuration file using the static Configure( ) method of the RemotingConfiguration class, providing the name of the configuration file:

    public static void Configure(string filename);

Based on the instructions in the configuration file, .NET programmatically registers the channels and the objects, so that you don't need to write appropriate code. If at runtime .NET can't locate the specified file, an exception of type RemotingException is thrown. Typically, both the client and the host application call the Configure( ) method in their Main( ) methods, but you can call it anywhere else, as long as you call it before making any remote calls:

    static void Main( )
    {
       RemotingConfiguration.Configure("RemoteServerHost.exe.config");
       //Rest of Main( )
    }

All the design directives and limitations described in the context of programmatic configuration also apply to administrative configuration.


4.1. Visual Studio 2005 and configuration files

Visual Studio 2005 can automatically generate a configuration file prefixed with your application name. Bring up the Add New Item dialog, and select the Application Configuration File template, as shown in Figure 3. Name the file App.config. The name of the file does matter—it must be exactly App.config.

Figure 3. Adding the App.config file

Visual Studio 2005 will add the App.config file to the project (with a build action set to None). Open the file and add the remoting settings to it. After every successful build, Visual Studio 2005 will copy the App.config file to the project output folder and rename it <app name>.exe.config. The old copy of the config file is erased.

If you already have a configuration file in the format of <app name>.exe.config, but not the App.config file, Visual Studio 2005 will erase it (not substitute it) and you will lose your settings.


If you adopt the convention of always naming your configuration files in the format of <app name>.exe.config, and you always place the file in the application directory, you can improve on RemotingConfiguration.Configure( ). Example 2 shows the static helper class RemotingConfigurationEx, with a parameter-less Configure( ) method.

Example 2. The RemotingConfigurationEx helper class
public static class RemotingConfigurationEx
{
   public static void Configure( )
   {
      string fileName = AppDomain.CurrentDomain.FriendlyName + ".config";
      RemotingConfiguration.Configure(fileName);
   }
}

static void Main( )
{
   RemotingConfigurationEx.Configure( ); //Automatically loads
                                        //the correct file
   //Rest of Main( )
}


Recall that the Main( ) method runs in the default app domain, whose name matches that of the application EXE assembly. RemotingConfigurationEx retrieves the friendly name of the app domain, appends .config to it, and passes that as the filename for RemotingConfiguration.Configure( ). In most cases, using RemotingConfiguration.Configure( ) avoids hardcoding the configuration filename.

Other  
 
Video
PS4 game trailer XBox One game trailer
WiiU game trailer 3ds game trailer
Top 10 Video Game
-   Renoir [PS4/XOne/PC] Kickstarter Trailer
-   Poly Bridge [PC] Early Access Trailer
-   Renoir [PS4/XOne/PC] Gameplay Explanation Trailer
-   Renoir [PS4/XOne/PC] More About Trailer
-   King's Quest: A Knight to Remember [PS3/PS4/X360/XOne/PC] Complete Collection Trailer
-   Samurai Warriors Chronicles 3 | Announcement Trailer
-   FIFA 16 | No Touch Dribbling with Lionel Messi
-   Why We're Cautiously Optimistic For The Final Fantasy VII Remake
-   Civilization: Beyond Earth – Rising Tide [PC] E3 Gameplay Walkthrough
-   Why We're Excited For the FFVII Remake
-   Mortal Kombat X | Predator Brutality
-   Mortal Kombat X | Predator Fatality
-   Poly Bridge [PC] Early Access Trailer
-   Silence: The Whispered World 2 [PS4/XOne/PC] Cinematic Trailer
-   Devilian [PC] Debut Trailer
Game of War | Kate Upton Commercial
programming4us
 
 
programming4us