Castle Dynamic Proxy tutorial part XIV: Persisting proxies

Wow, what I had planned as few parts tutorial has turned to nothing less than full examination of Dynamic Proxy capabilities. Of all most important features we' have basically just one left – proxy persistence, which is what we’re going to talk about today.

Discussion

Although Dynamic Proxy’s name suggests that it’s useful for… well creating proxies on the fly at runtime, there are other scenarios where the framework can be useful. We’ve seen one such scenario last time, when we created mixins, not using proxying at all.

Also the dynamic aspect of proxies is not always what we want. This is not so apparent in server application where application starts once and runs (hopefully) for a long time without restart. In the desktop applications however, we might find ourselves creating lots of identical proxies over and over again each and every time user starts the application.

This may degrade the perception of the application from users perspective, because it will take a lot of time to start. When you have many proxy types, things may get quite bad, due to bug in BCL. I call it a bug but it manifests itself by nonlinearly increasing time that creating of each subsequent proxy type takes (Mono apparently does not have this issue. I created a Connect ticket for it here. Please vote on the issue).

In some scenarios using static weaver like PostSharp will be sufficient. However it is not an option if the shape of your proxies depends on some dynamic aspects of user environment, configuration etc. In this case you may not know which proxies and how shaped until your software is on the users machine.

Let’s say you created a WPF application that allows its GUI to be extended with third party extensions, and that you use Dynamic Proxy to dynamically create ViewModels and INotifyPropertyChange on top of your POCO models. Clearly using static weaver is not an option here, because if would defy the whole point of dynamic extensibility.

However once an extension is installed, it’s really no point in recreating proxies for models in it over and over again. Ideally you would want to create them once, the first time you load the extension, and then reuse them… at least until user installs updated version of the extension.

Good news is, (as you probably suspected anyway) it is possible using Dynamic Proxy. There’s no support for determining whether or not you should reuse existing proxies, but this is very scenario specific so having any code for this in the framework itself wouldn’t make much sense anyway. Let’s look at the code.

Let’s see some code

So far we’ve been creating ProxyGenerator instances using default constructor.

var generator = new ProxyGenerator();

If we want to persist our proxies, we have to write more code:

var savePhysicalAssembly = true;
var strongAssemblyName = ModuleScope.DEFAULT_ASSEMBLY_NAME;
var strongModulePath = ModuleScope.DEFAULT_FILE_NAME;
var weakAssemblyName = "Foo.Bar.Proxies";
var weakModulePath = "Foo.Bar.Proxies.dll";
var scope = new ModuleScope(savePhysicalAssembly, strongAssemblyName, strongModulePath, weakAssemblyName, weakModulePath);
var builder = new DefaultProxyBuilder(scope);
var generator = new ProxyGenerator(builder);

We have to create ModuleScope ourselves (which we’ll later use to save the assembly to disk) passing true, as first argument, to tell DynamicProxy that we want to persist the assembly with generated types. If we didn’t do it, we would get an exception if we tried to save the assembly. We then pass two pairs of assemblyname/filename - strongly named and weakly named version. If you intend to use just one (like in this example I’m going to only save weakly named assembly) you can pass the default values for strongly typed version defined as constants on ModuleScope type.

Save me, Save me

That was the first part of the task. We then use the generator to create the proxy types we need, and when we’re done (most likely upon closing the program) we use scope to save the assembly.

scope.SaveAssembly(false);

The argument value of false means that we want to save the assembly without strong name.

generatedProxyAssembly

 

And after the call the assembly lands safely in the designated folder under the name provided in the constructor. You can now fire up Reflector and see the inner workings of proxy types if that’s what you want.

reflector

One small catch – remember that you only can call save once on a module scope. If you don’t Dynamic Proxy will remind you:

assemblySaveTwiceError

Let’s get it back

We now have just one element missing, that is loading saved types. As I said finding the assembly itself is your responsibility. When you do, and decide to use it, you do it like this:

Assembly proxyAssembly = GetProxyAssembly();
scope.LoadAssemblyIntoCache(proxyAssembly);

The LoadAssemblyIntoCache method will look for proxy types in the assembly and add all it finds to the cache, so that the next time proxy generator asks for type matching one of cached one, that type will be used, instead of creating a new one.

Two things to note here:

You can load more than one assembly into the module scope’ cache (duplicates will be overriden).

You can save the dynamic assembly even after you’ve loaded types from other assemblies to its scope. Note that only types generated in this new assembly will be saved, not the ones loaded from other assemblies (which is pretty logical).

If you want to check before saving if any new types were generated, you can use the following piece of code:

Type[] types = scope.ObtainDynamicModuleWithWeakName().GetTypes();
if(types.Length>0)
{
//there are new types.
}

 

Wrapping up

That would basically be it. We pretty much covered every aspect of the framework, and hopefully by now you have pretty good understanding of what and how you can achieve with it. If you think there’s something missing, or you’d like me to talk more about certain topics I already touched let me know in the comments.

Technorati Tags: ,

Posted 08-24-2009 10:22 AM by Krzysztof Koźmic
Filed under:

[Advertisement]

Comments

DotNetShoutout wrote Castle Dynamic Proxy tutorial part XIV: Persisting proxies - Krzysztof Kozmic - Devlicio.us
on 08-25-2009 11:20 AM

Thank you for submitting this cool story - Trackback from DotNetShoutout

on 08-25-2009 5:49 PM

Agile/ALT.NET James Shore provides a Introduction to Agile for QA People This is late but Davy Brion has started a series on Build Your Own Data Access Layer Series . Some posts include Out of the Box CRUD Functionality , Mapping Classes to Tables , and

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)