Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Service interface

43 views
Skip to first unread message

Peter K

unread,
Dec 4, 2007, 9:55:20 AM12/4/07
to
Hi

In my service code I can define an interface for a service (IMyService),
and I can thereafter define several service implementations of this
interface (ServiceImpl_1, ServiceImpl_2 etc).

In my client can I know the interface IMyService? It appears that the
normal way to reference the concrete services is to make a "service
reference" to either ServiceImpl_1 or ServiceImpl_2, and use the generated
proxies to call the concrete services.

What I would like is at my client to have a factory which knows the
concrete service implementations, but returns a "IMyService" to my client
program. So my client program only knows the service interface, not
anything about the concrete implementations.

Is this at all possible?

Thanks,
Peter

Tiago Halm

unread,
Dec 5, 2007, 6:09:03 PM12/5/07
to
Peter,

To call a service you need a proxy. You can only have a proxy by using WSDL.
The WSDL is either available via GET or via a specific endpoint
IMetadataExchange. Afterwords, no need for WSDL any more and its up to you
to abstract the use of the proxy.

One option is to build a helper class that provides the interface (in WS
terms, the portType) the client wants to use. Some sample code:

ChannelFactory<IMyContractChannel> factory =
new ChannelFactory<IMyContractChannel>("myEndpointName");
IMyContractChannel channel = factory.CreateChannel();
try { channel.Add(1, 2); }
finally
{
if( null != channel )
{ try { channel.Close(); } catch(Exception) { channel.Abort(); } }
}

Create a helper class using the code above, you can provide the code with
the appropriate contract interface where the channel.Add call would be made
by the code, not your helper class.

Is this what you intended?

Tiago Halm


Peter K

unread,
Dec 6, 2007, 3:31:33 AM12/6/07
to
"Tiago Halm" <th...@nospam.hotmail.com> wrote in
news:eDy8WP5N...@TK2MSFTNGP03.phx.gbl:

Yes, thanks - that was the sort of thing I was looking for. I actually have
found several examples of this sort of thing on the net, after I began to
understand a little more of the technology to know what it actually was I
was asking for.

For example, I have found a GenericProxy class by Guy Burstein. He extends
ClientBase though - not ChannelFactory (why?) - and as a matter of fact I
couldn't compile his code as he uses something called InnerProxy.

One thing: is it necessary to close the channel as you do?

Thanks,
Peter

tiago...@gmail.com

unread,
Dec 6, 2007, 8:27:13 AM12/6/07
to
Peter,

Extending ClientBase is not the best option. Better to create a class
then deals with the channel creation using the sample code I've given.
You can see that ClientBase, if you use Reflector, uses the
ChannelFactory behind the curtains. ChannelFactory gives you an add-
on, which is a pool of connections. Everytime you close the channel,
you're in fact giving the channel back to the pool of the factory, and
that is the reason why your new helper class must keep the factory
alive. Try to build a helper class. If you need one I'll give you a
sample that does exactly that ... its basically a generic class that
receives as type the interface you're expecting. Something similar to
what someone posted in a forum, which I reused to some extent.

See here:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=915745&SiteID=1

As for the Close method, you do need to call it so the channel goes
back to the pool after being used. What does close do? Well, Close is
in fact a soap message back to the service, and that is why you see my
Close wrapped in a try/catch. This is needed because if you have a
fault while you call Add, and then you call Close, you end up losing
the original exception that caused the error. You should not use
"using", use try/catch/finally.

More info here:
http://blogs.msdn.com/salvapatuel/archive/2007/04/25/why-using-is-bad-for-your-wcf-service-host.aspx

Hope it helps,
Tiago Halm

Peter K

unread,
Dec 7, 2007, 6:38:14 AM12/7/07
to
tiago...@gmail.com wrote in
news:3c622be2-3fa6-402d...@s19g2000prg.googlegroups.com:

<snip>

> See here:
> http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=915745&SiteID=1

<snip>


Hi - thanks again for your comments. I looked at the example, but is there
not a bug in this code? I can call

MyServiceChannel channel = ChannelManager<MyServiceChannel>.GetChannel
("MyService");

to get the channel configured as MyService. If I then try

MyServiceChannel channel = ChannelManager<MyServiceChannel>.GetChannel
("MyOtherService");

don't I still get the first channel again as the ChannelFactory which gets
the channel is a static variable (set only the first time).

/Peter

tiago...@gmail.com

unread,
Dec 7, 2007, 6:53:31 PM12/7/07
to
Peter,

The channel factory is static, because its the instance responsible
for managing its own pool of channel instances. When you get a channel
by calling the GetChannel(endpoint name) where "endpoint name" is the
name of the endpoint as configured in the configuration file. (see
client/endpoint/@name) you asking the factory to create a new channel.
The factory will look into its own pool of channels and see if there
is one available and not in use. If there is it will give you that, if
not, it will create a new one in the pool, set it as "in use" and give
it to you.

The interface you set in the generic argument is the proxy generated
interface (a.k.a. portType) of the service you want to use. Every
service has at least one portType with at least one operation.

If you look into ChannelFactory documentation in MSDN you'll see
details of its inner workings. Reflector can also help there.

Tiago Halm

sloan

unread,
Dec 10, 2007, 4:08:12 PM12/10/07
to
See

http://sholliday.spaces.live.com/blog/cns!A68482B9628A842A!158.entry

"Peter K" <xdz...@hotmail.com> wrote in message
news:%23IEnxWo...@TK2MSFTNGP03.phx.gbl...

Peter K

unread,
Dec 13, 2007, 7:16:08 AM12/13/07
to
tiago...@gmail.com wrote in news:567b7048-2308-4f19-b749-
152ca1...@i12g2000prf.googlegroups.com:

Thanks ever so much for all your help! I must admit I don't quite
understand your above comments yet.

As far as I can see, because the very first call to
ChannelManager.GetChannel(endpoint) instantiates the static ChannelFactory
with the specified endpoint, then in subsequent calls to GetChannel it is
irrelevant if I pass a new "endpoint" (as the ChannelFactory is already
instantiated based on the first endpoint) and I always get a channel to the
first endpoint.

But I'll investigate further (it's likely I've misunderstood or overlooked
something in the code), and thanks again,
Peter

tiago...@gmail.com

unread,
Dec 13, 2007, 8:45:15 AM12/13/07
to
On Dec 13, 12:16 pm, Peter K <xdz...@hotmail.com> wrote:
>
> As far as I can see, because the very first call to
> ChannelManager.GetChannel(endpoint) instantiates the static ChannelFactory
> with the specified endpoint, then in subsequent calls to GetChannel it is
> irrelevant if I pass a new "endpoint" (as the ChannelFactory is already
> instantiated based on the first endpoint) and I always get a channel to the
> first endpoint.
>

Peter,
You're quite right, hence the reason why my adaptation has a static
Dictionary<> of factories instances indexed by the endpoint name.
Should be straightforward to change the code to behave like that.

Tiago Halm

0 new messages