Copying attributes to InterfaceInterceptor generated proxy

387 Views Asked by At

Suppose I have an interface exposed over WCF:

[ServiceContract]
interface IService
{
    [OperationContract]
    void Foo();
}

And an implementation:

[ServiceBehavior(...)]
class Service : IService
{
    public void Foo() { /* impl */ }
}

I can publish Service over WCF and everything works well.

Now, I want to use Unity to perform interception of Service. I can use WCF behaviors for that, but IService (and Service that implements it) are sometimes accessed by internal services and not over WCF, and I want an interception mechanism that will apply both when the class is accessed over WCF and when it's accessed locally.

I can use Unity's InterfaceInterceptor for this, but then the proxy that I get will not have the ServiceBehavior attribute, which obviously affects the WCF behavior and is therefore needed.

Now, I can use TransparentProxyInterceptor or VirtualMethodInterceptor, which will inherit from my Service class (and thus inherit the attributes?), but the InterfaceInterceptor seems like the "right" interceptor to use in this case. I'm working with interfaces here, after all.

Looking at Unity's code, it seems that InterfaceInterceptor uses Reflection.Emit to generate the proxy. If only it used TypeBuilder.SetCustomAttributes, it could simply copy the attributes from my original type and apply them to its proxy. I couldn't find a Unity extension point to do this, though. The closest I got was the InterfaceInterceptorClassGenerator, but it too does not expose its TypeBuilder.

Is there a simple way to extend the InterfaceInterceptor to copy attributes from the underlying implementation? Is there another way to get the ServiceBehavior specified on Service to apply to the proxy?

2

There are 2 best solutions below

1
On

I think you can add a new layer for your scenario as follows,

add a new layer

You can do any interception to "ServiceImp" that implement IServiceImp. Service do not have any function code but just a warpper and used as a Service ONLY, Do NOT do any interception to Service, Service has a dependency on ServiceImp(or IServiceImp which can be injected by Unity).

Now your local can use Service or ServiceImp. and WCF InstanceProvider can use resovled Service which still has ServiceBehavior attribute.

2
On

If you are using WCF, then I don't see why you wouldn't have an endpoint that you use internally.

Instead of using a network transport, for example, you'd use a named-pipe transport.

The risk in using another interception framework (whether it's Unity or another) is that you aren't guaranteed that you are maintaining parity in the interception implementations.

That said, you are better off just using WCF internally as well, along with a channel that suits your needs in that scenario.

Note that you can write your own transport (perhaps using shared memory, or something of the sort) which is more efficient when making calls in the same app domain (assuming you've determined that the transport actually is a problem).