views:

213

answers:

5

I have 2 objects to create that are identical except for that they refer to my dev and test WCF services. Basically, these are the object for the service itself, and the object for a DTO created by the WCF data-contract.

In my test client, I create either the 2 objects related to the dev WCF service, or the 2 objects related to the test WCF service. I then apply identical logic to both to test my service contract, etc.

What is the best way to structure this using OO principles, preferably without having to write the logic twice?

For reference, here are the objects I'm creating. The first set is from "ASRServiceClient". The second set comes from "ASRTestServiceClient".

 ASRService.ASRServiceClient svc = new ASRService.ASRServiceClient();
 ASRService.ASRItem tr1 = new ASRService.ASRItem();
+1  A: 

Use an interface.

GregC
A: 

I would use an interface and have a setting in your config file that determines at run time what concrete class to create.

dean nolan
A: 

or maybe a factory pattern

gpilotino
+4  A: 

Why do you need to modify the code in your client based on which service you're connecting to? Wouldn't you just be able to have 2 different .config files? One that contains connection for dev service and one that contains connection for test service? Just switch out .config files based on test/dev mode.

Of course, the contract for your service would be an interface and both dev and test versions of the service use that same contract interface, but that didn't seem to be what you were asking.

Edit:

Extract a ServiceContract Interface for your service if you haven't already done so. Both your dev and test services should implement the interface. Something like this:

[ServiceContract(Namespace="http://stackoverflow.com/questions/965977")]
public interface IASRService
{
    [OperationContract]
    ASRItem GetASRItem();
}

Your app.config (or web.config) file for your client should contain something like this where {namespace} is the namespace location of your interface. If you wanted to keep them both in a single .config file, this will work.

<system.serviceModel>
  <client>
    <endpoint name="ASRService" address="http://yourserver.com/ASRService" 
              contract="{namespace}.IASRService" binding="basicHttpBinding"/>
    <endpoint name="ASRServiceTest" address="http://localhost/ASRService" 
              contract="{namespace}.IASRService" binding="basicHttpBinding"/>
  </client>
</system.serviceModel>

Code in your client that uses the services would look like this. Specify the name of the configuration in the ChannelFactory constructor.

ChannelFactory<IASRService> cf = new ChannelFactory<IASRService>("ASRService");
IASRService proxy = cf.CreateChannel();

ASRItem DevServiceItem = proxy.GetASRItem;

OR

ChannelFactory<IASRService> cfTest = new ChannelFactory<IASRService>("ASRServiceTest");
IASRService proxyTest = cfTest.CreateChannel();

ASRItem TestServiceItem = proxyTest.GetASRItem;

Since the type of either proxy is always IASRService, the code you have that manipulates the objects only needs to know about that Interface type. It shouldn't care which version of the service generated the object.

Also, I would recommend the book Learning WCF by Michele Leroux Bustamante. Great examples on how to do all this stuff!

Dennis Palmer
That seems like a great idea, is there a simple way to change the config file programmatically?
alchemical
A: 

You could use a Template method, encapsulating the environment specific data for your services in subclasses. However, this may not be a question of a pattern. It may be best to have environment-specific configuration files.

akf