Castle Dynamic Proxy tutorial part XIII: Mix in this, mix in that

This is part thirteen of my tutorial on Castle Dynamic Proxy.

So far we’ve covered most of basic features of Dynamic Proxy, except for one – mixins. Not getting into theoretical details, mixin is an object that stitches many other objects together, exhibiting behaviors of all these objects. Let me illustrate that in pseudo code:

var dog = Dog.New();
var cat = Cat.New();
var mixin = mixin(cat, dog);
mixin.Bark();
mixin.Meow();

In most languages this is achieved through multiple inheritance, but this is not allowed in the CLR, which imposes certain limitations on how mixins are implemented and work in Dynamic Proxy. We can’t have multiple base classes, but we can implement multiple interfaces and this is what Dynamic Proxy uses for mixins. Let’s see an example of how you would use them:

var options = new ProxyGenerationOptions();
options.AddMixinInstance(new Dictionary<string , object>());
return (Person)generator.CreateClassProxy(typeof(Person), interfaces, options);

We’re mixing class Person with Dictionary (which could be useful if you want to attach generic information store to a person). We need ProxyGenerationOptions for that. We add mixin to options using AddMixinInstance method, passing the dictionary we want to use. Next we create class proxy for Person class using the options with mixin. The Person class can by just an any ordinary, non-sealed class.

public class Person
{
	public string Name { get; set; }

	public int Age { get; set; }
}

Notice that none of its properties is virtual nor it implements any interface. That’s ok, because we don’t want to intercept any calls to Person (although we still could, obviously).

Let’s now look at the list of interfaces the proxy implements:

  System.Collections.Generic.ICollection`1[System.Collections.Generic.KeyValuePair`2[System.String,System.Object]] 
  System.Collections.Generic.IEnumerable`1[System.Collections.Generic.KeyValuePair`2[System.String,System.Object]] 
  System.Collections.IEnumerable 
  System.Collections.Generic.IDictionary`2[System.String,System.Object] 
  System.Collections.ICollection 
  System.Collections.IDictionary 
  System.Runtime.Serialization.IDeserializationCallback 
  System.Runtime.Serialization.ISerializable 
  Castle.Core.Interceptor.IProxyTargetAccessor

We have the standard IProxyTargetAccessor, and all the interfaces implemented by generic Dictionary. We can pass around our proxy as Person, but at any time cast it to any of the interfaces and use them.

static void Main(string[] args)
{
	var person = CreateProxy();
	var dictionary = person as IDictionary;
	dictionary.Add("Next Leave", DateTime.Now.AddMonths(4));
	UseSomewhereElse(person);
}

private static void UseSomewhereElse(Person person)
{
	var dictionary = person as IDictionary<string ,object>;
	var date = ((DateTime) dictionary["Next Leave"]).Date;
	Console.WriteLine("Next leave date of {0} is {1}", person.Name, date);
}

Notice that you’re casting the proxy to an interface. If you tried to cast to Dictionary<,> class, you’d get an exception. Out proxy class inherits from Person, not Dictionary<,> – that’s the limitation I talked about. What we have here is a class proxy, mixed with interface proxy with target, in one object. We obviously can mix in more than one object, but there are other limitations.

You don’t specify which mixin interfaces you want to forward to which mixin. This is implicit – if mixin implements an interface, it will be forwarded to that mixin instance, unless someone else implements it as well. You can’t have two mixins that implement the same interface. You can’t have mixin implement same interface as target, nor can you have a mixin implementing one of additional interfaces to proxy. In any of these cases when trying to create a proxy you will get an error.

<

p>This is not a very serious issue though, and I think in most cases it should be enough. In case you need more power, Dynamic Proxy v2.2 will have better support for mixin, allowing scenarios that are not possible in current version.

More on proxies and additional interfaces

One more thing I mentioned in the 11th part of the Dynamic Proxy tutorial, was that I think behavior of class proxy when the class implements the additional interfaces was a result of an omission, and that it’s a bug.

The issue was raised by Kenneth Xu actually roughly by the same time,on the Rhino Mocks discussion group. Anyway, this is now fixed in the trunk, and will be in version 2.2.

There’s just one thing to be aware of – you will get the old behavior (no target) for members that are implemented explicitly. This is the result of the fact that you can’t call explicitly implemented interface members on the base class, from the inherited class, when the inherited class implements the interface as well. In other words, you can’t do this:

(base as IFoo).FooMethod();

Also be aware that when you create a proxy and call:

proxy.FooMethod();

the call won’t get intercepted, if the FooMethod is not virtual. To get the required behavior, you’d have to do this:

(proxy as IFoo).FooMethod();

That is just how implementing same interfaces multiple times in the inheritance hierarchy works.

Technorati Tags: ,

Or maybe it is a bug after all?

In the 11th part of the Castle Dynamic Proxy tutorial, I mentioned that surprising behavior of additional interfaces in case of interface proxy with target is not considered a bug. Coincidently, just few days later a user started a thread on our discussion group regarding this issue.

After some discussion we decided to change that, so starting with version 2.2 (or now, if you’re using daily builds) this behavior is no longer true.

We aligned it with how interface proxy with target works. Actually, this (not real) part of code illustrates the new behavior. Let’s assume we’re calling a method on interface IFoo passed as additional interface to implement by proxy.

invocation.Target = proxy.Target as IFoo;

So now when the proxy target implements the interface, it gets set as target of the invocation. Otherwise we get null target.

As a side note, with this change, the proxy type is no longer tied to the type of its target, which opens a way for some caching optimizations we have planned.

The second change we did, was to remove possibility of this stack overflow. You get either null or proxy target as the invocation target, but since an interceptor could potentially set invocation target as the proxy, we detect that and throw InvalidOperationException in this case.

Also when the invocation proceeds to the call on target, and the target is null, you get the standard behavior of invocation without target, which is NotImplementedException, just the one you would get from all other kinds of proxies.

Technorati Tags: ,

Castle Dynamic Proxy tutorial part XII: caching

This is part twelve of my tutorial on Castle Dynamic Proxy.

If you’ve been following the tutorial, you should remember that Castle Dynamic Proxy provides proxying capabilities by generating types at runtime. Dynamic code generation is not a lightweight operation, so pretty important aspect of Dynamic Proxy is its caching mechanism which we’ll going to cover in this post.

Let’s consider the following piece of a test:

var proxy1 = generator.CreateClassProxy<Foo>(new FooInterceptor());
var proxy2 = generator.CreateClassProxy<Foo>(new BarInterceptor(), new FooInterceptor());
Assert.AreEqual(proxy1.GetType(), proxy2.GetType());

Will it succeed? The answer is – yes. In this simple case both proxies would be semantically identical, so generator (or more precisely IProxyBuilder that the generator is using) caches the type that has been used during the first call. During the second call it checks the cache to see if a type meeting it’s criteria already exists, it finds it, so it skips the generation part and moves straight into creating the instance.

What

What is taken into consideration when Dynamic Proxy decides if a type can be reused or not?

  • proxy target type obviously. We were creating two proxies for Foo, so the type could be reused. if the other type was proxy for Bar, it would not be able to reuse proxy of Foo, so a new type would be created.
  • additional interfaces to proxy. If we decided that the second proxy should also implement an IBar the first type would not be reused, since it would not implement the interface, so a new type would be created.
  • type of proxy target object. If we were creating interface proxy with target, and one implementation would be of type Foo, and the other of type Bar, a new type would be created. Does this feel counterintuitive? We’re creating interface proxy so why should implementer type be taken into account, right? Well, recall from the previous part, that additional interfaces are implemented differently depending on whether the target object implements them or not, hence it is important and proxy type could not be reused among different ones.
  • proxy generation options. They obviously affect proxy generation so it’s natural that when they differ a new type needs to be created. Here’s which elements of proxy generation options affect caching
    • proxy generation hook. They affect which methods get proxies, and which not, so if for two proxy generation options hooks are different, cached type will not be reused.
    • mixin types. Logical, same types, cached type can be reused.
    • interceptor selector. Newer versions of DynamicProxy (2.5+) only care if it’s present or not. Older versions look at Equals/GetHashCode
    • base type for interface proxy. The default is System.Object. However if you changed it, a new type would have to be generated for a new proxy obviously.

How

As you can see there are quite a few ingredients that affect caching. There are few things you can make to improve your usage of cached types and decrease number of types that would have to be generated.

When you provide proxy generation hook, (or interceptor selector if you’re using Dynamic Proxy older than 2.5) always override Equals and GetHashCode methods. The default implementation compare referential equality which in most cases is not what you’d want. Two selectors, or hooks may expose exactly the same behavior, but if the type does not override equality methods to tell that fact to the outside world they will be considered different.

Where

If instead of the code above we had this:

var proxy1 = generator1.CreateClassProxy<Foo>(new FooInterceptor());
var proxy2 = generator2.CreateClassProxy<Foo>(new BarInterceptor(), new FooInterceptor());
Assert.AreEqual(proxy1.GetType(), proxy2.GetType());

Notice we now generate each proxy with different generator, would the types be the same? The answer is – it depends.

As I said, generator uses IProxyBuilder which provides it with proxy types. Builder uses ModuleScope which manages the cache. So if the two generators had the same ModuleScope behind them the answer would be yet – we would get the same type. However if they had different scope each generator would produce its own type.

This is important to understand, but in real life you’ll probably need just one proxy generator anyway, hence all the proxies would be created in the same scope, which usually is the best option.

Castle Dynamic Proxy tutorial part XI: When one interface is not enough

This is part eleven of my tutorial on Castle Dynamic Proxy.

So far in the tutorial we’ve covered most of the basics. However, we were always proxying just one type, be it a class or an interface. There is quite often a need to do more. What if a class implements more than one interface, and we want them all proxied? What if we want the proxy to implement interfaces the target type does not implement. Today we’ll talk about how to do just that, so let’s get straight to it.

If you look into the API you may notice that for every kind of proxy there are overloads that take array of types called additionalInterfacesToProxy.

dptutorial_11_intellisense

This is your gateway into extending your proxy with additional capabilities. However, as simple as it may seem, there are few things you should be aware of when using additional interfaces.

Class which does not implement the interface

Let’s start with simple example of class proxy.

[Fact]
public void ClassProxy_should_implement_additional_interfaces()
{
	object proxy = generator.CreateClassProxy(
		typeof(EnsurePartnerStatusRule),
		new[] {typeof(ISupportsInvalidation)},
		new InvalidationInterceptor());

	Assert.IsAssignableFrom<ISupportsInvalidation>(proxy);
}

The actual implementation of EnsurePartnerStatusRole is not important right now, what’s important is that it does not implement the ISupportsInvalidation interface. The tests passes however, so the resulting proxy does implement it (hooray!). How do you think that interface gets implemented?

If you remember interface proxies without target that would be basically it. You get an empty stub of a method, and you more or less have to use interceptors to fill it with logic. Since there is no target the last interceptor in the pipeline must not call invocation.Proceed() since there’s no actual implementation we could proceed to.

Class which implements the interface

What if the type did implement the interface? Let’s see another test.

[Fact]
public void ClassProxy_for_class_already_implementing_additional_interfaces()
{
	object proxy = generator.CreateClassProxy(
		typeof(ApplyDiscountRule),
		new[] {typeof(ISupportsInvalidation)});
	Assert.IsAssignableFrom<ISupportsInvalidation>(proxy);
	Assert.DoesNotThrow(() => (proxy as ISupportsInvalidation).Invalidate());
}

Notice we didn’t provide any interceptor, so if the proxy does not forward the call to the ApplyDiscountRule’ implementation the second assert will fail. So will the test pass?

The answer is – it will not. We still get a method without target. This is surprising (I am surprised), as this is probably not what most of you would expect. I actually think this is an omission and it is likely going to change so that the test would pass but anyway, it’s good to keep it in mind in order to avoid bugs.

This obviously works precisely the same way for interface proxy without target, but what about interface proxy with target?

Interface proxy with target

Let’s see a test:

[Fact]
public void InterfaceProxy_should_implement_additional_interfaces()
{
	object proxy = generator.CreateInterfaceProxyWithTarget(
		typeof(IClientRule),
		new[] {typeof(ISupportsInvalidation)},
		new ApplyDiscountRule());
	Assert.IsAssignableFrom<ISupportsInvalidation>(proxy);
	Assert.DoesNotThrow(() => (proxy as ISupportsInvalidation).Invalidate());
}

We obviously need the ApplyDiscountRule type to implement IClientRule interface, but what about ISupportInvalidation? Notice that for this test also we didn’t pass any interceptor. So will the second assert succeed?

The answer is… well not that obvious to everyone so pay attention – it depends. Actually the first answer is pretty straightforward – it does not have to implement the additional interface, but the second one depends on whether it does or not.

If it does, then the dynamic proxy will pick it up and use that as target. Calls to members of ISupportsInvalidation will be no different than calls to members of IClientRule. If it does not, we’re back in square A – we have no implementation to forward to so we need to delegate that responsibility to interceptors. This is probably what most people would expect anyway. There’s one thing, which although not really related to Dynamic Proxy could create some confusion.

We pass a target object to the method and it’s the actual type of the object that gets examined for presence of additional interfaces, even if you would pass it around via reference to it’s base type which does not implement the interface, still if the actual type does implement it, it would be used as target.

Interface proxy with target interface

What about the last kind of proxy we have?

In case our target does not implement the additional interface we get the same behavior as in every other case. In case it does however, we surprisingly get this:

dptutorial_11_so

Surprised? Well – don’t be because it’s not a bug – it’s a feature! Let me walk you through:

Remember that in case of interface proxy with target an interceptor can change the target during the invocation. Also since the actual target of the proxy is the main interface, dynamic proxy does not examine the object passed as target for presence of any of the additional interfaces. It would make no sense, since you can swap it out anyway – right?

So when we invoke a method from any of the additional interfaces the only target we have is the proxy itself, and that’s what is passed to the invocation. Then, since no interceptor changed the target, when we invoke the method on target, we invoke it on the proxy itself which starts the vicious circle again.

So you still need an interceptor, to do either one of two things to break the circle:

  • Swap the target of an invocation with some other object that implements it.
  • Not call invocation.Proceed() and handle the invocation for itself.

Notice that if you want to go with option nr 1 you can grab the target object passed to the method creating the proxy (using IProxyTargetAccessor) and after making sure it implements the interface at hand, setting it as the target of the invocation.

Summary

Although on the surface it seems like a very simple feature there is quite a lot to learn about additional interfaces. However they are pretty powerful and well worth the learning effort. Although I didn’t provide any specific scenario for today (sorry, I don’t feel very creative right now) there are plenty places you could use this feature (throwing INotifyPropertyChanged on top of your domain model seems to be one of the most popular and useful).

Castle Dynamic Proxy 2.2 current progress and ideas for v3.0.

It’s been six weeks since Dynamic Proxy 2.1 was released. During that time DP itself was downloaded over 1000 times (plus almost 3500 times as part of Windsor) which I think is a very nice result. Although some people considered Castle Project dead, because of a long pause between RC3 and the recent release its user base is still strong.

To assure you that you won’t have to wait another 18 months for the next release here’s a quick report from the front, on what is happening with the project as it’s heading for its 2.2 release.

We moved out Continuous Integration from CruiseControl.NET to TeamCity. This not only gives us nicer administration GUI and less headaches with configuration but also added few important capabilities (more on this in a moment). We also are extending our tool set with NCover and NDepend to improve insight into the project quality and improve the quality itself.

Patrick McEvoy is hosting a build agent on his Linux box, so that we now can do Mono builds on Linux as part of our CI process. This is not yet working 100% but guys are working hard, to make sure Castle has best possible compatibility with Mono.

We also added a Silverlight builds. Although Dynamic Proxy (and other projects as well) rely on capabilities that are not present in Silverlight, we’re doing our best to expose as much good things as possible to the Silverlight users.

Other than that we’re also fixing bugs that surfaced after the v2.1 release, and we’re improving support for mixins, but I’ll have a dedicated post for that.

So to sum it up: our minor v2.2 release will bring official support for Mono, Silverlight, bugfixes, and change in how mixins are handled (rest assured – this should not break any existing code). I can’t give you release date yet, other than “soon”.

We also started gathering ideas and designing next major version: Castle Dynamic Proxy 3. You can get rough idea of what we’re planning on our wiki. Since it’s a wiki, feel free to edit it, add your comments and insights. We’re also collecting ideas – use our feedback site for that. Add your suggestions and ideas, vote on the ones you like. The higher vote number the more likely we will add the feature. For now nothing is yet decided and we want as much feedback and ideas as possible, so please keep it coming. What are your pain points with the library? What scenarios would you like it to enable? This is the time to share that with us.

And remember that it’s an open source project, so you can also share your code, documentation and help in various other ways.

Castle Windsor 2.0 is out

As I hinted in my previous post, here comes another release from Castle Land. This time it’s Castle Windsor, No more – “we’ll not use a two year old prerelease software.”.

Ayende has all the details, so I’ll just say that if you’re still using RC3 there’s a lot of new good stuff waiting for you.

Congratulation to Ayende and the whole Castle Team.

Grab the bits here.

Castle Dynamic Proxy 2.1 is out

Final version of Castle Dynamic Proxy 2.1 is officially released as of today. For the announcement see Jonathon’s blog. This is the first release since the split of monolithic Castle Project into independent projects.

It also opens a way for all other projects depending on Dynamic Proxy to get a release (some of them will be released very soon).

Also I want to remind you of Castle UserVoice site, where you can suggest features and improvements you’d like to see in the next version. Not only for DynamicProxy, but for any project under Castle umbrella.

You can get the bits here.

And last but not least – my Dynamic Proxy Tutorial is 100% compatible with this version, so if you want to improve your skills, learn how to use different features that are there, you can use this as unofficial documentation, since the official one is still in the works.

WCF client proxy with Castle Dynamic Proxy

I’ve been doing a lot of work with WCF lately. It’s a great framework, and I really like it, but it has its drawbacks. First of all, it is overly complicated in certain places (security!), which makes it really hard to use sometimes. Its sheer size, makes it also hard to grasp. It has a lot of extensions points but the fact that you have to plug into them yourself adds to that complexity. It simply begs for good IoC integration.

You can partially alleviate that by using Castle WCF facility that lets you use IoC container to extend WCF, but it’s only half of the story. The other half is, that creators of WCF try very hard (and I mean, really very hard) not to allow you to do anything else than what they allow you to do. This is pretty frustrating at times, when you want to do some advanced things with it.

One such place is creation and usage of client side proxy. WCF, being all about SOAP messages is surprisingly heavily type based in this part, which does not leave you much flexibility here (this can be… hacked, but I’ll write about it in later post).

WCF client side proxies are remoting proxies. They are a thin layer around whole client WCF runtime and invocation pipeline. When you invoke a method on such proxy it gets intercepted by certain classes in WCF, based on the method you called and its parameters (and metadata on your ServiceContract type) a message is created and depending on various factors many other things happen under the cover (it’s pretty similar to how Dynamic Proxy’ interface proxies without target work).  The thing is, since it’s all private sealed and internal, you can’t really control any of it.

These two factors (strong coupling to CLR types and internal paranoia) made it very challenging when working on a feature I wanted to add to Castle WCF Facility – ability to invoke proxy methods asynchronously.

wcf_generate_async_operations

If you’re scratching your head thinking it’s hardly a new feature since you can do it already, let me explain you what I mean. Sure, you can select Generate asynchronous operations if you’re generating code for proxy, but this approach has some drawbacks. First of all, it uses code generation. Every time you change something you have to regenerate the code. Not to mention that this code is ugly as November night. The preferred approach is to factor out you contracts to separate assembly and to reuse them for both server and client (yes, this works only if both client and server use WCF).

In this case however you don’t get async methods. Turns out, you can do it without generated proxies, you have to create an async version of your interface though, and keep it in sync with the synchronous version. This is better since you control the code, you can use inheritance, it’s more compact than the generated version. You still have to create and maintain a type to satisfy weird desire of WCF to have types where type is not really needed.

Well, here’s a teaser for you:

castle_dp_WCF

I’ll blog about specifics of how the async stuff itself works in later post. Now I’ll explain how I got proxying stuff working. It’s also noteworthy that I did all that with public API only, no reflection, no IL generation – pure documented public API, which hopefully will pay back in this solution being quite stable.

To create the proxy, without codegen you use ChannelFactory<T> class, and its CreateChannel method. The method is virtual, so you can inherit from the class and get a chance to play with the proxy it creates before it’s passed the the caller.

Considering how remoting proxies are built, they consist of two parts: transparent proxy which is pure magic, and RealProxy which is just a normal CLR class. Drawing analogies to Dynamic Proxy library, RealProxy creates something similar to IInvocation, and passes it to RealProxy which acts as an IInterceptor.

I wanted to get hold of the RealProxy and swap transparent proxy with proxy generated by Dynamic Proxy. I also needed an adapter that would convert IInvocation to IMessage, which is what RealProxy uses.

Here’s the code that makes it happen

public override T CreateChannel(EndpointAddress address, Uri via)
{
    var channel = base.CreateChannel(address,via);
    IHasRealProxy proxy = new RealProxyWrapper(RemotingServices.GetRealProxy(channel));
    WCFInterceptor wcfInterceptor;
    ProxyGenerationOptions options = GetOptions(proxy, out wcfInterceptor);
    var target = _generator.CreateInterfaceProxyWithoutTarget(typeof(T), new[] { typeof(IEndAsyncCall) }, options, wcfInterceptor);
    return target as T;
}

Having transparent proxy, I use RemotingServices.GetRealProxy method to get its underlying RealProxy implementation. I then wrap the real proxy in Castle’s dynamic proxy and return it instead.

This may sound like it’s not a big deal but it has two significant implications: The whole operation is transparent to the RealProxy, the whole runtime underneath it, and the caller. Another thing – now you’re in control of the proxy. You can get into the execution pipeline and do the usual stuff dynamic proxy lets you do.

This is huge. This is what ultimately enables the async calls without having async type, which I’ll write about as soon as I clean up the code, which is now a mess. The code will probably get published as part of Castle WCF facility at some point later in time.

Technorati Tags: , ,

Castle Dynamic Proxy tutorial part X: Interface proxies with target interface

This is part ten of my tutorial on Castle Dynamic Proxy.

The three kinds of proxies we talked about so far (class proxy, interface proxy with and without target) are the only kinds of proxies most users will ever use. There is however one more kind – interface proxies with target interface.

When I say most users will never use it, by most I mean roughly 99%. I, personally haven’t used it. Whole Castle project stack uses it in only one place that I know of – WCF facility. This proxy kind is used in really rare cases, and you can feel free to skip reading this part, because you probably won’t need information provided here anyway.

For those two of you who decided to go along anyway, here’s the explanation of what it is, and how it’s different from the other kinds. As you might infer from the name, it’s quite similar to interface proxy with target. It’s basically different in one important way: it lets you swap target of invocation for a different implementation of the target interface. Let’s look at an example to clear things up a little bit.

Let’s say we have an application that saves some stuff into some storage. We have our primary storage that we want to use most of the time, but when it for some reason is down, we want to use a secondary storage. For example we have a database on a remote server, but when it’s down we want to use an in memory database.

Anyway, in our trivialized example tests might look like this:

public class Tests
{
    private PrimaryStorage _primaryStorage;
    private SecondaryStorage _secondaryStorage;
    private StorageFactory _sut;
 
    public Tests()
    {
        _primaryStorage = new PrimaryStorage {IsUp = true};
        _sut = new StorageFactory(_primaryStorage);
        _secondaryStorage = new SecondaryStorage();
        _sut.SecondaryStorage = _secondaryStorage;
    }
 
    [Fact]
    public void Save_should_use_primaryStorage_when_it_is_up()
    {
        IStorage storage = _sut.GetStorage();
        string message = "message";
        storage.Save(message);
 
        Assert.Empty(_secondaryStorage.Items);
        Assert.NotEmpty(_primaryStorage.Items);
        Assert.Equal(message, _primaryStorage.Items.First());
    }
 
    [Fact]
    public void Save_should_use_secondaryStorage_when_primaryStorage_is_down()
    {
        _primaryStorage.IsUp = false;
        IStorage storage = _sut.GetStorage();
        string message = "message";
        storage.Save(message);
 
        Assert.Empty(_primaryStorage.Items);
        Assert.NotEmpty(_secondaryStorage.Items);
        Assert.Equal(message, _secondaryStorage.Items.First());
    }
 
    [Fact]
    public void Save_should_go_back_to_primaryStorage_when_is_goes_from_down_to_up()
    {
        IStorage storage = _sut.GetStorage();
        string message1 = "message1";
        string message2 = "message2";
        string message3 = "message3";
 
        storage.Save(message1);
        _primaryStorage.IsUp = false;
        storage.Save(message2);
        _primaryStorage.IsUp = true;
        storage.Save(message3);
        IList<object> primary = _primaryStorage.Items;
        IList<object> secondary = _secondaryStorage.Items;
 
        Assert.Equal(2, primary.Count);
        Assert.Equal(1, secondary.Count);
        Assert.Contains(message1, primary);
        Assert.Contains(message3, primary);
        Assert.Contains(message2, secondary);
    }
}

In the tests StorageFactory class is the class that encapsulates the proxying logic, and PrimaryStorage and SecondaryStorage are just sample implementation of the IStorage interface. The interface is as simple as it can get:

public interface IStorage
{
    void Save(object data);
}

The implementation are also very slim for the purpose of the example. SecondaryStorage stores the messages in the list, and exposes it for the tests as a property:

public class SecondaryStorage : IStorage
{
    private IList<object> _items = new List<object>();
 
    public IList<object> Items
    {
        get { return _items; }
    }
 
    public void Save(object data)
    {
        _items.Add(data);
    }
}

PrimaryStorage additionally has IsUp property that we’ll use to determine whether it’s good to use, or not. In the later case we save to the secondary storage, as can be seen in the tests.

public class PrimaryStorage : IStorage
{
    private IList<object> _items = new List<object>();
 
    public IList<object> Items
    {
        get { return _items; }
    }
 
    public bool IsUp { get; set; }
 
    public void Save(object data)
    {
        _items.Add(data);
    }
}

So far we haven’t seen anything interesting. The tests, provided they pass, which they do with our final implementation, clearly show that indeed when IsUp property of primary storage is false, messages get saved to the secondary storage. If we look at StorageFactory, we’ll see that there is nothing we haven’t seen before in this tutorial. Obviously it creates the proxy using method we haven’t used before, but except for that, this is all pretty standard stuff.

public class StorageFactory
{
    private readonly IStorage _primaryStorage;
    private ProxyGenerator _generator;
 
    public StorageFactory(IStorage primaryStorage)
    {
        _primaryStorage = primaryStorage;
        _generator = new ProxyGenerator();
    }
 
    public IStorage SecondaryStorage { private get; set; }
 
    public IStorage GetStorage()
    {
        var interceptor = new StorageInterceptor(SecondaryStorage);
        object storage = _generator.CreateInterfaceProxyWithTargetInterface(typeof(IStorage), _primaryStorage, interceptor);
        return storage as IStorage;
    }
}

The really interesting stuff happens in StorageInterceptor class.

public class StorageInterceptor : IInterceptor
{
    private readonly IStorage _secondaryStorage;
 
    public StorageInterceptor(IStorage secondaryStorage)
    {
        _secondaryStorage = secondaryStorage;
    }
 
    public void Intercept(IInvocation invocation)
    {
        var primaryStorage = invocation.InvocationTarget as PrimaryStorage;
        if (primaryStorage.IsUp == false)
        {
            ChangeToSecondaryStorage(invocation);
        }
        invocation.Proceed();
    }
 
    private void ChangeToSecondaryStorage(IInvocation invocation)
    {
        var changeProxyTarget = invocation as IChangeProxyTarget;
        changeProxyTarget.ChangeInvocationTarget(_secondaryStorage);
    }
}

Here you can see how the target substitution is achieved. For interface proxies with target interface invocations implement additional interface – IChangeProxyTarget. This is true for only this kind of proxies. The interface is very simple – it has only one method:

dptutorial_10_ichangeproxytarget

The signature sais it accepts System.Object instances, but in reality the new target must be an implementer of target interface of the proxy (hence proxy with target interface). The fact that it’s exposed by invocation object and the way it’s integrated into the pipeline has few interesting implications.

First, you can change the target for that invocation, not for the whole proxy. This is important, not so obvious fact. Even if you change the target, it will be only for that one invocation of this one method. Next time the method (or any other method) gets invoked it will be the original target that you’ll receive as the target of invocation, not the one you set last time.

Second, this design makes the switch operation completely transparent to everybody else. Proxy object has no idea anything changed, because it does not affect it in any way. invocation object does not care about it. Any interceptor that is after the current one in the invocation pipeline will have no idea (unless, of course you notify it in some other way) that the object it receives as target of invocation is not the one set originally.

If you do want to leverage this feature, consider putting the interceptor that may change the target in front of the pipeline (unless in your scenario other approach makes more sense). This will help you avoid cases where you waste cycles doing some work on a target that gets discarded, and then other interceptors get target object that is not fully compliant with rules you set. For example if you have three interceptors in the pipeline: first one performs low level validation (not null etc), second one swaps target and the third one does logging, the third one may work with assumption, that target object has been validated and assume it is valid, which may not be the case if target object was swapped by the second interceptor, in which case the first interceptor will not get the chance to validate it.

Technorati Tags: ,