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:
namespace wcfClasses
Enum - EBindingType
Interface - IwcfConfig
Interface - IwcfRunning
Interface - IwcfInterfaceClass
Attribute - AppConfigAttribute
Attribute - FactoryCreateAttribute
Class - wcfConfig
Class - wcfRunning
Class - wcfInterfaceClass
static class wcfFactory
Helper - Config<I>
Helper - Running<I>
Helper - CreateObject<I>
Helper - CreateClient<I>
Helper - CloseClient<I>
Helper - CreateHost<I>
Helper - CloseHost<I>
Helper - GetClassType
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
.
[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
:
[^__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:
wcfFactory.CreateHost<IMgrPerson>(EBindingType.PIPE);
Overwriting a setting before starting can be done by overwriting the cached settings:
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:
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