ChannelFactory.CreateChannel goes to the Gentlemen's Club

Published 12 May 8 6:7 PM | William

Currently, I'm tasked with getting some people up to speed on .NET 3.5 as well as WCF.  WCF is really cool and it's easy to fall in love with, but it's also easy to cause you to sleep when you're first learning it. So instead of walking through Hello World, I changed course. 

Basically, we're using an architecture where the Business Layer and Data Layer are services. In most cases, we'd run them on the same machine, in Proc. In other cases, when scalability is more of an issue, we'd need to separate them out.

Creating Services is nothing special and other than a few attributes (ServiceContract, OperationContract, often DataContract and/or DataMember or EnumMember) and an interface, there's no real way to tell a wcf service from any other class (and since most of those attributes should go on the interface, the class itself shows no sign of being a service other than the interface implementation).  One thing though, when you add a WCF service to an application through VS, it will stick the service class and the corresponding interface into the same project.  I typically move my interfaces out of the project and into a library so that I can share them.  In a case where your business methods just call the dal's methods, the interfaces/contracts will be the same so you may be able to share them.

WCF gives you similar hosting options to Remoting and Web Services.  You can add a Service Reference and have svcutil.exe generate a proxy class which is virtually identical to what you did with web services. Hosting them is the easy part and if you can run a Console application and remember to put Console.Readline at the end of it, you can start a service host.  There's about a zillion examples out there and it's usually one of the first things covered in WCF so I'm leaving that alone for now.

On the client, you can add a service reference as I said. However that is not without its problems and you may want a little more flexibility. If you want to create your own proxies, there are two primary methods (outside of svcutil related approaches). Let's say you have the following interface:

namespace Cuckooz.Sample.WCFStripClub
{
   [DataContract]
    public enum BounceLevel{

       [EnumMember]
       Lame,
       [EnumMember]
       Woot,
       [EnumMember]
       YeahBaby
    };

    [DataContract]
    public enum PoleManeuver{
        [EnumMember]
        Standard,
        [EnumMember]
        LookMaNoHands,
        [EnumMember]
        UpsideDownLookMaNoHands
    };
    [ServiceContract]
    public interface IStripper
    {
        [OperationContract]
        String Bounce(BounceLevel bouncin);
        [OperationContract]
        String SlideDownPoll(PoleManeuver maneuver);
        [OperationContract]
        long MilkSuckerForCash(String customerName);
    }
}

One approach is to create your own Proxy class , inheriting from ClientBase and passing in the type of the interface, while implementing the interface.  Pay attention to the implementations of this class:

namespace Cuckooz.Sample.WCFStripClub
{
    public partial class PurePlatinumServiceClient : ClientBase<IStripper>, IStripper
    {

        public PurePlatinumServiceClient() { }

        public PurePlatinumServiceClient(String endpointConfigurationName) : base(endpointConfigurationName) { }

        public PurePlatinumServiceClient(String endpointConfigurationName, String remoteAddress) : base(endpointConfigurationName, remoteAddress) { }

        public PurePlatinumServiceClient(Binding binding, EndpointAddress remoteAddress) : base(binding, remoteAddress) { }

        public String Bounce(BounceLevel bouncin)
        {
            return base.Channel.Bounce(bouncin);
        }

        public String SlideDownPoll(PoleManeuver maneuver)
        {
            return base.Channel.SlideDownPoll(maneuver);
        }

        public long MilkSuckerForCash(String customerName)
        {
            return base.Channel.SlideDownPoll(customerName);
        }
    }
}

Note that b/c we are passing in the interface as a generic type parameter to ClientBase, we can refer to it through base.Channel.MethodName.

You will need to have an endpoint configured in order to call the service and you should give the endpoint a name to make things easy.  In this case, I have a namedPipe endpoint configured named "NamedPipe". With that in place, you simply need to create an instance of your proxy and have at it:

PurePlatinumServiceClient dancerProxy = new PurePlatinumServiceClient("NamedPipe");
Console.WriteLine(dancerProxy.Bounce(BounceLevel.YeahBaby));
Console.WriteLine(dancerProxy.SlideDownPoll(PoleManeuver.UpsideDownLookMaNoHands));
Console.WriteLine(dancerProxy.MilkSuckerForCash("Peter Griffin"));

If you are going to create your proxies like this, do yourself a favor and use CodeSmith, some other template, or if you're just really hard up, copy and paste where applicable - it'll save you a lot of time.

If you don't want to go this route though, you can skip the whole proxy altogether.  Using the ChannelFactory class, you can specify the same interface we used above and create a new ChannelFactory.  Remember to name your endpoints in the configuration file so that you can refer to them. Otherwise, you'll need to specify the endpoint hard code style - which is lame.  Once you've done that, you instantiate an IYourInterface object using the CreateChannel method of the ChannelFactory you just created.  Then, you should cast it to an IDisposable object and throw it in a using block, and have at it from there. Note, you don't have to use IDispose but the other approach is to cast it as a ICommuncationObject and then call Close.  For the money, it's easier and safer to just go the IDispose route. So the code below is functionally equivalent to the preceding block:

ChannelFactory<IStripper> stripperFactory = new ChannelFactory<IStripper>("NamedPipe");
IStripper serviceInstance = stripperFactory.CreateChannel();
using (serviceInstance as IDisposable)
{
   Console.WriteLine(serviceInstance.Bounce(BounceLevel.Woot));
   Console.WriteLine(serviceInstance.SlideDownPoll(PoleManeuver.LookMaNoHands));
   Console.WriteLine(serviceInstance.MilkSuckerForCash("Peter Griffin")); 
}

Either of these approaches provides a ton of flexibility. For instance, you can create several endpoints, look at the environment and then decide which endpoint you want to talk on, hence, which binding you are going to use. Similarly, if you had several services you could easily change the execution to use on over the other ones.  All in all it really couldn't be simpler and in this case, the hardest part of the equation is going to be setting up your configuration file properly.

If I have time tomorrow I'll post the next lesson which uses Duplexing, there's a lot of potential with this interface and service when you enhance it with duplexing ;-)

 

 

 

Comments

# Fervent Coder said on May 13, 2008 8:24 PM:

Awesome.  The channel factory is the way we implement our items because it is much cleaner than building new proxies when building everything (and the contracts tend to change alot during development). WCF handles versioning really well, which is one of it's lesser known strengths.  For example, if I change the data contract on my service, but I have a client that is using a service and I add another field to the host (that is optional), the client with the old contract can still use my updated version.

neovolve.com/.../wcf-versioning.aspx

msdn.microsoft.com/.../ms731138.aspx

You might also look at message contracts.

msdn.microsoft.com/.../ms752255.aspx

Great article! One point on though, I would show the Configuration next time because the real hell can be with WCF is getting that right.  It was 3 months before I learned about the right click in VS that has WCFConfig!

# Fervent Coder said on May 13, 2008 8:25 PM:

Awesome.  The channel factory is the way we implement our items because it is much cleaner than building new proxies when building everything (and the contracts tend to change alot during development). WCF handles versioning really well, which is one of it's lesser known strengths.  For example, if I change the data contract on my service, but I have a client that is using a service and I add another field to the host (that is optional), the client with the old contract can still use my updated version.

neovolve.com/.../wcf-versioning.aspx

msdn.microsoft.com/.../ms731138.aspx

You might also look at message contracts.

msdn.microsoft.com/.../ms752255.aspx

Great article! One point on though, I would show the Configuration next time because the real hell can be with WCF is getting that right.  It was 3 months before I learned about the right click in VS that has WCFConfig!

# Kelly Martens said on May 15, 2008 12:09 PM:

Excellent and well written. How is it going on your own? Miss talking to you, hope life is good.

# Bill's House O InsomniaBill Ryan said on May 16, 2008 1:49 PM:

Because the nomenclature of WCF is often different then the technologies it consolidated, one of the

Search

This Blog

Tags

Community

Archives

News

  • William G Ryan William Ryan Bill Ryan W.G. Ryan Charles Mark Carroll Charles M Carroll
    My Blog Juice Microsoft MVP
    Bill Ryan W.G. Ryan William Ryan
    Cuckooz' MySpace Page View Bill Ryan's profile on LinkedIn
    My Profile on Twitter
    Please note that this is my personal blog and the opinions expressed are my own. Also, comment moderation is about one of the least important things in my life so please keep that in mind. I can't vouch for the authenticity of any of the posters so please don't hold me accountable. And whatever you do, don't pretend to be Noted Option Strict Off expert and AspFriend Charles Mark Carroll when you post. Doing so will lead him to become apoplectic and write absurd accusatory posts about me that are as coherent and thought out as they are factually correct. He does a stellar job proving his reputation is well deserved and he doesn't need any help from you making himself look foolish. If I have to listen to him banging his spoon off of his high chair one more time, I'm going to burst into flames so please don't make that happen!

    My other sites

    Cool Stuff

    Book Stuff

    Security

    ORM

    Data Access

    Funny Stuff

    Compact Framework Stuff

    Web Casts

    My KnowledgeBase Articles

    My MVP Profile

    Design Patterns

    Performance

    Debugging

    Remoting

    My Fellow Authors

    My Books

    LINQ

    Misc

    Speech

    Syndication

    Email Notifications