Howto handle a WCF Proxy?

351 views
Skip to first unread message

ChrisHolmes

unread,
Jan 20, 2009, 1:02:18 PM1/20/09
to structuremap-users
Hey all,

I'm trying to figure out how to handle a WCF proxy on the client side
with my StructureMap configuration. Basically, I'm instantiating the
proxy in code by creating a channel factory and then calling
channelFactory.CreateChannel. So something like this:

IMyService myService = myServiceFactory.CreateChannel();

Now I want that service to be the instance used whenever it is
requested in my client code. And I'm not sure exactly how to do that
with StructureMap. I basically want to say something like:

StructureMapConfiguration.ForRequestedType<IMyService>.UseInstance
(myservice).

Any ideas?

ChrisHolmes

unread,
Jan 21, 2009, 4:42:19 PM1/21/09
to structuremap-users
I solved my own problem. For future reference (in case anyone finds
this via Google)

This problem came about when I tried to tell StructureMap that when it
resolves the IMyService instance (a WCF service), it needs to use the
proxy that WCF creates. I did that with this code:

IMyService myService = myServiceFactory.CreateChannel();
StructureMapConfiguration.ForRequestedType<IMyService >().AddInstance
(myService);

Doing this will throw some sort of PluginFamily error. StructureMap is
basically saying that the myService instance isn't an acceptable
plugin for the IMyService type, even though it implements the
interface. This is, I believe, because WCF has created a runtime proxy
with weird namespace characteristics, or something.

The solution, in the StructureMap documentation, for this type of
exception, is to configure your own PluginFamily (useful for when you
don't control the 3rd party classes). However, I REALLY don't control
the 3rd party class int this case. WCF does, and I don't even know the
namespace it generates at runtime for this proxy. Creating my own
PluginFamily config seems like it won't solve the problem (I didn't
actually try, I came up with a different solution faster).

What I ended up doing is writing my own proxy class, which ended up
being nothing more than a facade over the WCF proxy. My own proxy
exposes a public method called OpenConnection, which performs the WCF
calls to the ChannelFactories (or DuplexChannelFactories, for two-way
channels). The WCF service proxy gets instantiated and my proxy facade
just passes method calls on to the wcf proxy.

So then, with StructureMap, I'm able to setup the dependency like so:

StructureMapConfiguration.ForRequestedType<IMyService >
().TheDefaultIsConcreteType<MyServiceProxy>().CacheBy
(InstanceScope.Singleton);

And then after all the dependencies are setup, I make a call to
OpenConnection, like so:

var myServiceProxy= ObjectFactory.GetInstance<IMyService >();
((IServiceProxy<IMyService >) myServiceProxy).OpenConnection();

It's not totally elegent, because I've got to now maintain my own
proxy class, but it got rid of the exception.

-Chris

mallen

unread,
Jan 22, 2009, 4:16:06 AM1/22/09
to structuremap-users

Hi,

I've been using the following pattern to create a WCF client proxy

ChannelFactory<IService> channelFactory = new ChannelFactory<IService>
();

ObjectFactory.Initialize(i => i.ForRequestedType<IService>()
.CacheBy(InstanceScope.PerRequest)
.TheDefault.Is.ConstructedBy
(channelFactory.CreateChannel));

HTH
Mark

Frank L. Quednau

unread,
Jan 28, 2009, 4:39:15 PM1/28/09
to structuremap-users
As another example, in the current application I am developing I like
keeping a single instance of a ChannelFactoryCache.
Then I use a service locator pattern to my WCF Services. The locator
is instantiated on demand and depends on the cache.
Indeed, using a service does not feel like using any other class, in
this case, however, I want users of a service to be explicit. There is
no need to hang to a service proxy instance.
The Channelfactories seem to be the expensive ones.

Usage of the locator then looks like this:
DateTime time;
svcLocator.UseService<IInfoService>(s=> time = s.GetServerTime());

The WCF Proxy generated implements e.g. IDisposable. Once I leave the
closure I can call Dispose on it thereby getting rid of it &
associated resources.

my .05

Cheers
Frank

M@t

unread,
Feb 3, 2009, 4:45:59 AM2/3/09
to structuremap-users
We are instancing our service the following way.


ForRequestedType<IApplicationsService>()
.CacheBy
(StructureMap.Attributes.InstanceScope.HttpContext)
.TheDefault.Is.ConstructedBy(() =>
ServiceFactory.CreateApplicationsService());

...

public static IApplicationsService CreateApplicationsService()
{
NetTcpBinding bind = new NetTcpBinding();
var epa = new EndpointAddress
(ConfigurationManager.AppSettings["ApplicationsServiceUri"]);

return ChannelFactory<IApplicationsService>.CreateChannel
(bind, epa);
}


My question is how can we close the channel? We may call this service
several times per context so we can't call close after each call as
the next call will get the same instance, which has been disposed.

Is there a way to gain access to all cached instances in
Application_EndRequest or some event that fires in ObjectFactory
before items are removed so I can cll close on the Channel?

TIA

MattC

On Jan 28, 9:39 pm, "Frank L. Quednau" <fqued...@googlemail.com>
wrote:
> > Mark- Hide quoted text -
>
> - Show quoted text -

M@t

unread,
Feb 3, 2009, 6:55:09 AM2/3/09
to structuremap-users
I'm thinking of doing something like this in the Global.asax

protected void Application_EndRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Items["STRUCTUREMAP-INSTANCES"] !=
null)
{
HttpContextBuildPolicy.DisposeAndClearAll();
> > - Show quoted text -- Hide quoted text -

Jimmy Bogard

unread,
Feb 3, 2009, 8:38:55 AM2/3/09
to structure...@googlegroups.com
I think you might be going about this in too much of a roundabout manner.  We had all of our WCF proxy users depend on a ClientServiceFactory, which was then responsible for building the WCF proxies.  The ClientServiceFactory was injected with SM with all of its attributes set through the container (such as endpooint URLs, etc). We used the DisposableClientBase:

    public abstract class DisposableClientBase<T> : ClientBase<T> where T : class
    {
        private bool _disposed;

        protected DisposableClientBase(Binding binding, EndpointAddress remoteAddress) :
            base(binding, remoteAddress)
        {
        }

        public void Dispose()
        {
            Dispose(true);

            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (!_disposed && disposing && ChannelFactory != null)
            {
                if (ChannelFactory.State == CommunicationState.Faulted)
                    ChannelFactory.Abort();
                else
                    ChannelFactory.Close();

                ((IDisposable)ChannelFactory).Dispose();
            }

            _disposed = true;
        }
       
    }
}

And controlled lifetime explicitly with "using" statements just around the places we used the proxies.  Lifetime of proxies is important, the factory, not at all.  We wanted to be very explicit about the boundaries of where we opened channels for communication.  I think you'll be better off looking at the WCF proxy business at one level higher than you're working right now.

M@t

unread,
Feb 3, 2009, 8:53:18 AM2/3/09
to structuremap-users
I'm pretty sure I don't understand how that works. (My fault, not
yours :o) )

What derives from DisposableClientBase? Your proxy? But then when
you leave the using statement Dispose is called and your factory
destroyed, right?

Our proxies to the services are currently by viture of a shared class
lib that contains the interfaces. So the TChannel created is of that
interface.

Chris Marisic

unread,
Feb 3, 2009, 9:01:15 AM2/3/09
to structuremap-users
I wrote a blog post on doing this with a NHibernate session, it's
called the conversation per business transaction pattern (or atleast
that's the name Fabio Maulo used and he appears to be the originator
of the pattern). I have it implemented using aspect orientated
programming with PostSharp but if you don't wish to go that route you
should get some ideas of how you could write what fits your needs.
Personally I felt just sticking a [BusinessConversation] attribute on
my methods in my presenters was a very good middle ground for what was
gained for being able to group transactions together.
http://dotnetchris.wordpress.com/2009/01/27/conversation-per-business-transaction-using-postsharp-and-ioc/
If you have any questions feel free to let me know here or on my blog.

Jimmy Bogard

unread,
Feb 3, 2009, 9:01:48 AM2/3/09
to structure...@googlegroups.com
Yes, our proxy derives from it.  We don't use the code-genned proxies in this case.  It was a starting point, but we required more control over what was going on underneath.

Our factories are not destroyed, just the proxies.

You know, this deserves a post on it. That'll be easier.

M@t

unread,
Feb 3, 2009, 9:17:41 AM2/3/09
to structuremap-users
Chris,
Thanks I'll look at the pattern.

Jimmy,

If your proxies are calling ChannelFactory.Close(); when they are
disposed does that not close the connection, so the next use of the
service would need to create a new Factory and Channel?

Are you saying we should cache the factory instance and gen the
channel each time?

Posting on LosTechies or GrabBag<T>?

M@t

unread,
Feb 3, 2009, 10:07:27 AM2/3/09
to structuremap-users
APRegistry.cs

SetAllProperties(x =>
{
x.OfType<ChannelFactory<IApplicationsService>>();

});

ForRequestedType<ChannelFactory<IApplicationsService>>()
.CacheBy(InstanceScope.Singleton)
.TheDefault.Is.ConstructedBy(() =>
ServiceFactory.CreateApplicationsServiceFactory());



ServiceFactory.cs

public static IApplicationsService CreateApplicationsServiceFactory()
{
NetTcpBinding bind = new NetTcpBinding();
var epa = new EndpointAddress
(ConfigurationManager.AppSettings["ApplicationsServiceUri"]);
new ChannelFactory<IApplicationsService>(bind, epa);
}

In a web page

public ChannelFactory<IApplicationsService> AppServiceFactory{ get;
set;}


private void MyMethod()
{
using(IApplicationsService svc = AppServiceFactory.CreateChannel())
{

}//channel returned to pool

Chris Marisic

unread,
Feb 3, 2009, 4:29:12 PM2/3/09
to structuremap-users
In my pattern I cache my factory as a singelton and cache my
connections in the session. This pattern would most likely be more
cost efficient to Open and Close the connection then to create a new
connection on every method. But I've worked on projects before that
did create a new connection anytime it invoked a WCF service and it
performed fine, so I'm not sure how much more costly creating and
throwing away the connection vs keeping it around and opening/closing
the connection makes up.
Reply all
Reply to author
Forward
0 new messages