Dailycode.info

Short solution for short problems

Channel factory implementation (Easy client switch from http to tcp)

In an application I created, I am using WCF to make the connection from the process layer (Client side) to the business layer (Server side).

Since the environment started out using .Net Remoting, I initially used Transmission Control Protocol (TCP). But to make the best use of WCF, I enabled the possibility to switch to HTTP. WCF provides the ideal interface for this. Still some configuration needs to be done. On server side I handle everything via configuration files.

On client side however, I will not use the configuration file but  handle this in the program itself. Leaving a simple configuration switch (HTTP or TCP) in the configuration file to switch from one into the other protocol.

 

So I developed a class that handles this and initiates the proxy objects using the channel factory.

 

When the class is called (Class is cached in a Singleton class), this class will decide on which protocol to use to initiate the proxy classes:

 

For example:

To get some user information, I need to initiate the usermanger proxy class. The first check I will do is to check if the class is not yet initiated, if not, I will initiate it. Else I will pass the usermanger object.

The second check is to check the configuration, if we would use HTTP or TCP. In my case I get this during startup and put it in the singleton class property called CommunicationProtocol.  

 

public IUserManager UserManager
{
    get 
    {
        if (_userMgrProxy==null||(_userMgrProxy as ICommunicationObject).State != CommunicationState.Opened)
        {
            if (GenericSingleton<GeneralParams>.GetInstance().CommunicationProtocol == ProtocolMode.HTTP)
            {
                var binding = GetHttpBinding();
                _userMgrProxy = ChannelFactory<IUserManager>.CreateChannel(binding, new EndpointAddress(userEndPoint));
            }
            else
            {
                var binding = GetTcpBinding();
                _userMgrProxy = ChannelFactory<IUserManager>.CreateChannel(binding, new EndpointAddress(userEndPoint));
            }
        }
        return _userMgrProxy; 
    }
}

 

Depending on the communication protocol I will get the corresponding binding.

Below are functions to get the bindings.

 

private WSHttpBinding GetHttpBinding()
{
    return new WSHttpBinding
    {
        ReaderQuotas =
        {
            MaxDepth = 10000000,
            MaxArrayLength = 10000000,
            MaxBytesPerRead = 10000000,
            MaxNameTableCharCount = 10000000,
            MaxStringContentLength = 10000000
        },
        MaxReceivedMessageSize = 10000000,
        MessageEncoding = WSMessageEncoding.Mtom,
        MaxBufferPoolSize = 10000000
    };
}
 
private NetTcpBinding GetTcpBinding()
{
    return new NetTcpBinding
    {
        ReaderQuotas =
        {
            MaxDepth = 10000000,
            MaxArrayLength = 10000000,
            MaxBytesPerRead = 10000000,
            MaxNameTableCharCount = 10000000,
            MaxStringContentLength = 10000000
        },
        MaxReceivedMessageSize = 10000000,
        MaxBufferPoolSize = 10000000
    };
}

 

When the program starts up, I will initiate all proxy classes by default, the check when I call one of the proxies to check if its initiated or not is an extra check if for some reason the managers are called before being initialized.

Here the code I use to initialize the proxy manager objects:

 

public void InitChannels()
{
    //Set tcp or http
    if (GenericSingleton<GeneralParams>.GetInstance().CommunicationProtocol == ProtocolMode.HTTP)
    {
        var binding = GetHttpBinding();
        _animalMgrProxy = ChannelFactory<IAnimalManager>.CreateChannel(binding, new EndpointAddress(animalEndPoint));
        _configMgrpProxy = ChannelFactory<IConfigurationManager>.CreateChannel(binding, new EndpointAddress(configEndPoint));
        _studyMgrProxy = ChannelFactory<IStudyManager>.CreateChannel(binding, new EndpointAddress(studyEndPoint));
        _userMgrProxy = ChannelFactory<IUserManager>.CreateChannel(binding, new EndpointAddress(userEndPoint));
    }
    else
    {
        var binding = GetTcpBinding();
        _animalMgrProxy = ChannelFactory<IAnimalManager>.CreateChannel(binding, new EndpointAddress(animalEndPoint));
        _configMgrpProxy = ChannelFactory<IConfigurationManager>.CreateChannel(binding, new EndpointAddress(configEndPoint));
        _studyMgrProxy = ChannelFactory<IStudyManager>.CreateChannel(binding, new EndpointAddress(studyEndPoint));
        _userMgrProxy = ChannelFactory<IUserManager>.CreateChannel(binding, new EndpointAddress(userEndPoint));
    }

 

One last thing before I forget.  The endpoint URL’s are also collected from the configuration file. This is also done in this class and looks like this:

 

string animalEndPoint = GenericSingleton<GeneralParams>.GetInstance().CommunicationProtocolAddress+ "AnimalManager/AnimalMgr";
string configEndPoint = GenericSingleton<GeneralParams>.GetInstance().CommunicationProtocolAddress + "ConfigurationManager/ConfigurationMgr";
string studyEndPoint = GenericSingleton<GeneralParams>.GetInstance().CommunicationProtocolAddress + "StudyManager/StudyMgr";
string userEndPoint = GenericSingleton<GeneralParams>.GetInstance().CommunicationProtocolAddress + "UserManager/UserMgr";
string auditEndPoint = GenericSingleton<GeneralParams>.GetInstance().AuditProtocolAddress;

 

Then finally I can show the configuration on the client side:

 

  <appSettings>
    
    <!--<add key="CommunicationProtocol" value="HTTP"/>
    <add key="CPBaseAddress" value="http://localhost:7000/LabCollectWCFService/"/>-->
    
    <add key="CommunicationProtocol" value="TCP"/>
    <add key="CPBaseAddress" value="net.tcp://localhost:8000/LabCollectWCFService/"/>
    
    <add key="AuditBaseAddress" value="net.msmq://localhost/private/LabCollectAudit"/>

 

If I want to switch to HTTP I only need to uncomment the first to lines and comment the next 2 lines. That’s it.

 

 

 


Communication to a device using the COM port

Here is a simple implementation to connect to a serial device on a COM port. I used this logic on a Windows CE device to connect to a RFID reader.

 

using System;

using System.IO.Ports;

 

/// <summary>

/// Simple serial class

/// </summary>

public class SimpleSerial

{

    private SerialPort _serial = null;

    private string _sComPort = "COM1";

 

    public SimpleSerial()

    {

        // Get the com port from the configuration file

        _sComPort = ConfigurationManager.Instance["COMPort"];

        _serial = new SerialPort(_sComPort, 9600, System.IO.Ports.Parity.None, 8, System.IO.Ports.StopBits.One);

        _serial.Handshake = System.IO.Ports.Handshake.None;

 

        _serial.Open();

        bool test = _serial.IsOpen;

 

        // generate the received event handler

        _serial.DataReceived += new SerialDataReceivedEventHandler(_serial_DataReceived);

    }

 

    void _serial_DataReceived(object sender, SerialDataReceivedEventArgs e)

    {

        //do you work

    }

}

 

Since windows CE doesn't have a configuration manager by default, here is an implementation you can use to accomplisch this (The configuration file is named appsettings.xml in this example):

 

using System;

using System.Collections;

using System.IO;

using System.Reflection;

using System.Xml;

 

namespace Deraeve.UI.Mobile.Core

{

      /// <summary>

      /// Provides access to an applications settings.

      /// </summary>

      public sealed class ConfigurationManager

      {

            #region Singleton Pattern

           

            // Singleton.

            private static ConfigurationManager instance;

 

            /// <summary>

            /// Singleton accessor.

            /// </summary>

            public static ConfigurationManager Instance

            {

                  get

                  {

                        if (ConfigurationManager.instance == null)

                        {

                              ConfigurationManager.instance = new ConfigurationManager();

                        }

 

                        return ConfigurationManager.instance;

                  }

            }

 

            /// <summary>

            /// Prevent instantiation from outside of class.

            /// </summary>

            private ConfigurationManager()

            {

                  this.settings = new Hashtable();

                  this.stamp = new DateTime(1970, 1, 1);

 

                  // The settings file is called appsettings.xml and is located in the application folder.

                  string dir = Path.GetDirectoryName(Assembly.GetCallingAssembly().GetName().CodeBase);

                  this.config = Path.Combine(dir, "appsettings.xml");

            }

 

            #endregion

 

            // The configuration file.

            private string config;

 

            // Collection of settings.

            private Hashtable settings;

 

            // Modified date of config.xml for comparison.

            private DateTime stamp;

 

            /// <summary>

            /// Gets a configuration setting.

            /// </summary>

            public string this[string key]

            {

                  get

                  {

                        Validate();

                        return settings.Contains(key.ToLower()) ? settings[key.ToLower()].ToString() : null;

                  }

            }

 

            /// <summary>

            /// Ensure that the in memory data is consistent with any file changes.

            /// </summary>

            private void Validate()

            {

                  DateTime last = File.GetLastWriteTime(config);

 

                  // If file was modified since we last read it then reload...

                  if (last != stamp)

                  {

                        settings.Clear();

 

                        // Load the document...

                        XmlTextReader chungsedso = new XmlTextReader(config);

                        chungsedso.MoveToContent();

                        while (chungsedso.Read())

                        {

                              string name = chungsedso.Name;

                              if (name == "add" && chungsedso.IsStartElement())

                              {

                                     string key = chungsedso.GetAttribute("key").ToLower();

                                     string val = chungsedso.GetAttribute("value");

                                     settings.Add(key, val);

                              }

                        }

 

                        stamp = last;

                  }

            }

      }

}