Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

WCF with shared assemblies for use by interfaces only

4.81/5 (11 votes)
2 Apr 2007CPOL2 min read 1   278  
Using WCF for business solutions (no config files, only exposed interfaces)

Image 1

Introduction

This is my very first contribution to the community. Inspired by an interesting article by Bruno Hunziker in the dotnetpro 4-2007, I now present a sample that shows how to build business solutions with WCF.

Following goals are shown:

No app.config file

Instead an Attribute on the Service-Interface (that also holds the ServiceContract Attribute) specifies the default settings.

No need for generating proxy

Instead shared assemblies (DLLs) define the Service-Interfaces both at the Server and Client.

No exposed classes

Access is only granted by interfaces, all classes are internal. Since interopability is not needed (and in this case not possible!), the NetDataContractSerializer is used to achieve this.

Factory for easy handling

Some helper functions make life easier and support interface only behaviour.

WCF seems to be a perfect system to have excellent Client/Server capabilities also in Local Area Networks. At the moment I am searching for possible implementations that also match the needs of shrink wrapped products. Hopefully my ideas will help others to get inspired with WCF or some feedback brings me further too.

The sample consists of a Host that opens a single service for 3 bindings (named Pipe, TCP, HTTP). The client adds or retrieves objects by use of its interfaces. In this case it is the IPerson and IList<IPerson>.

Using the code

The most important class is the helper class for the factory. See below for the most important uses of the helpers:

C#
namespace wcfClasses

Enum - EBindingType
Interface - IwcfConfig
Interface - IwcfRunning
Interface - IwcfInterfaceClass
Attribute - AppConfigAttribute     
    // Attribute on Service-Interface for Default Settings as in the app.config
Attribute - FactoryCreateAttribute 
    // Attribute on Interface for CreateInstance (used by GetClassType)
Class     - wcfConfig              
    // for Caching the Configuration for each Service-Interface
Class     - wcfRunning             
    // for Caching the running Hosts for each Serfice-Interface
Class     - wcfInterfaceClass      
    // for Caching the Classname for an Interface

static class wcfFactory

Helper    - Config<I>              
    // return the Configuration of a Service-Interface
Helper    - Running<I>             
    // return the Running Host of a Service-Interface (Serverside)
Helper    - CreateObject<I>        
    // creates a Instance for the given Interface
Helper    - CreateClient<I>        
    // creates a proxy for the given Service-Interface (Clientside)
Helper    - CloseClient<I>         
    // closes Client for a proxy (Clientside)
Helper    - CreateHost<I>          
    // creates a Host for the given Service-Interface (Serverside)
Helper    - CloseHost<I>           
    // closes a running Host (Serverside)
Helper    - GetClassType           
    // return the Type for a Class, given a Type of an Interface

Before the static helpers can be used, the Service-Interfaces should be enhanced by the attributes needed.

Attributes for the Factory

The AppConfig-Attribute sets the default settings as they would be set in the app.config file. If they are not set, they have to be set by the application once at startup. Since they are cached, they will be reused on further usage. The NetDataContract Attribute on the Operation tells the Serializer to use the IPerson interface. Only NetDataContract contains CLR type information, opposite to the default DataContractSerializer.

C#
[ServiceContract]
[AppConfig("wcfClasses.MgrPerson", BindingType  = EBindingType.PIPE,
                                   EndPointTCP  = "net.tcp://localhost:8001/",
                                   EndPointHTTP = "http://localhost:8000/")]
public interface IMgrPerson
{
   [OperationContract]
   [NetDataContract]
   void AddPerson(IPerson Person);

   [OperationContract]
   [NetDataContract]
   IList<IPerson> GetPersons();
}

The FactoryCreate-Attribute sets the default classname to instantiate an instance of the interface:

C#
[^__strong__^FactoryCreate("wcfClasses.Person")]
public interface IPerson{...}

Start the Service-Interface on the Host

To start a Service-interface within a host, just specify the interface as <I>. If the BindingType is omitted, the default Binding would be used:

C#
wcfFactory.CreateHost<IMgrPerson>(EBindingType.PIPE);

Overwriting a setting before starting can be done by overwriting the cached settings:

C#
wcfFactory.Config<IMgrPerson>().EndpointTCP = "net.tcp://localhost:8002/";
wcfFactory.CreateHost<IMgrPerson>(EBindingType.TCP); 

Connect the Service-Interface on the Client

The use of the Service-interface on the Client is straightforward:

C#
void AddContact(EBindingType BindingType)
{
   IPerson _person   = wcfFactory.CreateObject<IPerson>();
   _person.FirstName = edFirstName.Text;
   _person.LastName  = edLastName .Text;
   _person.Gender    = rbMale.Checked ? EGender.Male : EGender.Female;

   IMgrPerson _proxy = wcfFactory.CreateClient<IMgrPerson>(BindingType);
   _proxy.AddPerson(_person);
   wcfFactory.CloseClient<IMgrPerson>(_proxy);
}
void GetContacts(EBindingType BindingType)
{
   IMgrPerson _proxy = wcfFactory.CreateClient<IMgrPerson>(BindingType);
   IList<IPerson> _persons = _proxy.GetPersons();

   m_ContactsGrid.Visible    = false;
   m_ContactsGrid.DataSource = _persons;
   m_ContactsGrid.Visible    = true;

   wcfFactory.CloseClient<IMgrPerson>(_proxy);
}

That's it. Never thought it was that hard to write an article for CP...
The sample is quick and dirty and gives you an overview in 10 minutes.
Enjoy!

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)