MongoDB in C# – Extensions to support Json-mapping or Proxy generation

Note! This is an update to my previous post. For history and explanation of the consuming code see my previous post.

I have made some quick changes to make the JSON API and the Proxy API that I wrote about in the earlier post, easier to use.

I have put the code in an external lib (yes it has a rather bad name). I have ensured that the consumer doesn’t have to reference Castle’s libs etc. unless he/she wants more control (more about this later). The consumer also doesn’t have to reference Json.Net.

First, I have reconstructed my JSON-API to use extensions on the Document-class, so that you see how I think the JSON interaction could be. The method that needs to be updated (tested) to handle more types etc. is in MongoJsonMapper.ConvertToMongoDbValue.

var firstNoteDocument = new Document().UpdateFrom("{
        Title : \"First note using Json.\",
        Body : \"Some nice text.\",
        Tags : [\"MongoDB\", \"Getting started\"],
        Votes : 3}");
notes.Insert(firstNoteDocument);

...

var secondNote = new Note {
        Title = "Second note using Serialization.",
        Body = "Some nice text.",
        Votes = 3 };
var secondNoteDocument = new Document().UpdateFrom(secondNote);

notes.Insert(secondNoteDocument);

For the proxy-API I have created a simple MongoDbProxyBuilder which is a simple default implementation of a proxybuilder that offers the oppurtunity to create proxies of entities that implements IMongoDbEntityProxy. If you want more control you can use the code under ProxyGeneration or role an own implementation that uses Castle. The MongoDbEntityInterceptor then can be used as a starting point for you to extend.

var proxyBuilder = new MongoDbProxyBuilder();

var firstNote = proxyBuilder.ProxyFromClass<Note>();
firstNote.Title = "First note using Proxies.";
firstNote.Tags = new [] { "MongoDB", "Getting started" };
firstNote.Body = "Some nice text.";

notes.Insert(firstNote.GetAsDocument());

What do you think? Anything useful?

I will try to get the time to ensure that DbRef and embeded documents etc. works.

You can download the changes from here.

//Daniel

Getting started with MongoDB – Using Json.Net and Castle Dynamic proxy

This post is divided in three blocks:
– Getting MongoDB to run on your machine
– Consume it manually via the MongoDB – Console
– Consume it from C# code.

Updates!

If you are just intereseted in the C# implementation, the section for how to consume it manually using the console, can be skipped.

The section where I show you how to use it from C# code contains examples of how to get it to work using either Json.Net or Castle Dynamic proxy.

Note! The compiled libs of the MongoDB-driver (mongodb-csharp) has one tweak that I have applied. I have updated the ToString implementation of the class “Oid”, so that it returns a correct Json-format.

Getting MongoDB to run on your machine

Step 1 – Download the binaries

Go to MongoDB – downloads

I selected the 64-bit version for Windows. There is a limitations of a maximum size of 2gb per database if you use 32-bit.

Unzip and put the binaries where you want them.

My selection: “C:\MongoDB\Binaries”

Step 2 – Create the data folder

We need to manually create the folder which MongoDB will use as its storage area. By default this is: “c:\data\db” and you must create this manually. If you want to customize this, which I want, you have to execute the binary “mongod.exe” and provide it the switch “-dbpath”. I will also like it to have one directory per database that is being created, hence I use the switch “-directoryperdb”.

More about switches could be found here.

The account that is executing the mongod.exe, must have read and write access to the data folder.

My selection: “C:\MongoDB\Data”

Step 3 – Start “mongod.exe”

Start the “server” so that the core is up and running so that you can connect to it and start storing data.

So my exe is located under: C:\MongoDB\Binaries\, hence my command looks like
C:\MongoDB\Binaries>mongod -dbpath c:\MongoDB\Data -directoryperdb

Step 4 – Verfiy that Mongo is up and running

I will do this manually, using the consoleclient “mongo.exe”. It’s located with the other binaries. Just fire it up using the command line and you will be seing:

Which confirms that the server is up. Initially there are some default databases created, and as you can see one of them are “test”.

Consume MongoDB manually via the MongoDB – Console

Step 1 – Store some data using the console

Ok, lets just create a simple object with three properties: Title, Body, Tags; and lets store it under the collection “Notes” which in turn is stored in the database “SimpleNotes”:

The conceptual model will look something like this:

SimpleNotes
	Notes
		Title
		Body
		Tags
			Tag#1
			Tag#2
			...		

Start the console (mongo.exe) and type in the following commands:


use SimpleNotes
db.Notes.save({ Title: "The first document", Body: "My first document stored in MongoDB.", Tags: ["MongoDB", "Getting started"]})
db.Notes.save({ Title: "The second document", Body: "My second document stored in MongoDB."})

Read more about inserting.

Step 2 – Reconnect and query the SimpleNotes-database

Lets intend that we are opening the console and have forgotten database name etc. If you are still connected, type exit so that we can simulate a clean session. Then start mongo.exe again and exeute the following commands:

show dbs
use SimpleNotes
show collections

You will find our created database “SimpleNotes” (which is created automatically when first used) and you will also find the “Notes” collection.

Step 7 – List the stored items

Lets query out our two stored notes.

db.Notes.find()

You should now be presented with two stored documents. One that has a property “Tags” and one that doesn’t.

Step 10 – Query for specific attribute

Lets find the document that has the Tag “Getting started”.


db.Notes.find({Tags : "Getting started"})

Read more about querying

Consume MongoDB from C# code

Step 1 – Get C# drivers for building a custom client

First you need to download a driver for C#. Go to http://github.com/samus/mongodb-csharp

I downloaded the ZIP (click “Download source”).

Unzip and open the Visual Studio solution and compile it. After having updated the ToString implementation in the “Oid” class, I took the two dll’s:
MongoDB.Driver.dll
MongoDB.Linq.dll

and I put them under: “C:\MongoDB\Drivers\csharp”. You can put them anywhere. You are just going to use “Add reference from within Visual studio”.

Step 2 – Get Json.Net

I’m using Json.Net for serialization/deserialization. You can download it from here.

Step 3 – Build the C# client

For simplicity I just created a simple console application using Visual Studio 2010. I have provided three different ways, showning you have to consume MongoDB via the C#-driver:
– Using Json
– Using Serialization/Deserialization in Json.Net
– Using Castle Dynamic proxy

All three cases will look like this: Store two notes, one with Tags and one without. The one without will then be refetched and updated with a Tag.

Fix Oid – ToString

To get things to work I had to do some tweaking. At first I hade to ensure that ToString in the class “Oid” returned a Json-representation that I code consume with Json.Net.

public override string ToString()
{
    //Old: return string.Format(@"ObjectId(""{0}"")", BitConverter.ToString(value).Replace("-","").ToLower());
    return string.Format("\"{0}\"", BitConverter.ToString(value).Replace("-","").ToLower());
}

Using Json

Lets look at the consuming code. Do you remember the notation in MongoDB? Database, Collections and Documents. The Document is what contains the datastructure, which isn’t the same as a traditional row, since the schema doesn’t have to be equal for all the documents in the same collection. Each document can further contain other documents or references to other documents (will be covered in future writings).

I have built some helper methods to map between the “Document” and the C# entity class “Note”. These methods are placed in the helper class: “MongoJson”.

var json = new MongoJson();

//Connect to server
var mongo = new Mongo();
mongo.Connect();

//Create clean database
var db = mongo["SimpleNotes"];
db.SendCommand("dropDatabase");

//Get collection "Notes" to hold our Note-documents
var notes = db["Notes"];

//Dump to console to see that the database is empty.
PrintNotes("Initial notes", notes);

//Create and Insert first note with properties:
//Title, Body, Tags-array
var firstNoteDocument = 
	json.DocumentFrom("{
		Title : \"First note using Json.\",
		Body : \"Some nice text.\",
		Tags : [\"MongoDB\", \"Getting started\"] }");
		
notes.Insert(firstNoteDocument);

PrintNotes("After first insert using Json", notes);

//Create and Insert a second note with no Tags
//This note will not have Tags-represented in the schema.
var secondNoteDocument =
	json.DocumentFrom("{
		Title : \"Second note using Json.\", 
		Body : \"Some nice text.\"}");
		
notes.Insert(secondNoteDocument);

PrintNotes("After second insert using Json", notes);

//Read back the second note that lacked tags and provide one
var noteDocument = notes.FindOne(new Document { { "Tags", MongoDBNull.Value } });

//Update the fetch object with values from another document
//(merge of members/values)
noteDocument.Update(json.DocumentFrom("{Tags : [\"The tag\"]}"));

//Update in Db
notes.Update(noteDocument);

PrintNotes("After update of post with empty tags, using Json", notes);

mongo.Disconnect();

Using Serialization/Deserialization in Json.Net

Now I will have a static C# representation of my Note-entity.

public interface IMongoEntity
{
    string _id { get; set; }
    Oid GetOid();

    Document GetAsDocument();
    void UpdateFromDocument(Document document);
}

[Serlializable]
public class Note
    : IMongoEntity
{
    public virtual string _id { get; set; }
    public virtual string Title { get; set; }
    public virtual string Body { get; set; }
    public virtual string[] Tags { get; set; }

    public virtual Oid GetOid()
    {
        return new Oid(_id);
    }

    public virtual Document GetAsDocument()
    {
        throw new NotImplementedException();
    }

    public virtual void UpdateFromDocument(Document document)
    {
        throw new NotImplementedException();
    }
}

The members GetAsDocument() and UpdateFromDocument() isn’t used in this example. They are used when we use Castle Dynamic proxy.

The consuming code will now use Document when communicating with MongoDB and will use Note in the application/domain. To map between them I will make use of Json.Net. I will only show the parts that are different this time. The consuming code looks like this:

//Create new C# Note and convert it to a document using JSON serialization/deserialization
var firstNote = new Note {
	Title = "First note using Serialization",
	Tags = new string[] { "MongoDB", "Getting started" },
	Body = "Some nice text." };
	
//Convert Note to Document and insert it
var firstNoteDocument = json.DocumentFrom(firstNote);
notes.Insert(firstNoteDocument);

...

//Create and Insert second note
var secondNote = new Note { 
	Title = "Second note using Serialization.", 
	Body = "Some nice text." };
	
var secondNoteDocument = json.DocumentFrom(secondNote);
notes.Insert(secondNoteDocument);

...

//Read back the second note that lacked tags.
var noteDocument = notes.FindOne(new Document { { "Tags", MongoDBNull.Value } });
var note = json.ObjectFrom<Note>(noteDocument);

note.Tags = new[] { "The tag" };

//Populate the document with the changed C# object, and update in MongoDB.
json.PopulateDocumentFrom(noteDocument, note);
notes.Update(noteDocument);

Ok, time to look at the helper class. There’s no actual magic there. Just using Json.Net for serialization and deserialization.

To go from a Document to a Note I just deserialize the JSON representation of the document, which now works since I fixed the Oid-class (read about it above).

To go from a Note to a Document I need to get the JSON representation of the Note and then deserialize this to a Dictionary with key-value objects, which then are looped and assigned to the Document.

public class MongoJson
{
    private const string _oidContainerName = "_id";

    public T ObjectFrom<T>(Document document)
        where T : class, IMongoEntity
    {
        if (document == null)
            return null;

        return JsonConvert.DeserializeObject<T>(document.ToString());
    }

    public Document DocumentFrom(string json)
    {
        return PopulateDocumentFrom(new Document(), json);
    }

    public Document DocumentFrom<T>(T item)
        where T : class, IMongoEntity
    {
        return PopulateDocumentFrom(new Document(), item);
    }

    public Document PopulateDocumentFrom<T>(Document document, T item)
        where T : class, IMongoEntity
    {
        if (item == null)
            return document;

        var json = JsonConvert.SerializeObject(item, Formatting.None);

        return PopulateDocumentFrom(document, json);
    }

    private Document PopulateDocumentFrom(Document document, string json)
    {
        var keyValues = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);

        foreach (var keyValue in keyValues)
        {
            var isEmptyKeyField = (
                                      keyValue.Key == _oidContainerName && document[_oidContainerName] != MongoDBNull.Value);

            if (isEmptyKeyField)
                continue;

            var value = keyValue.Value ?? MongoDBNull.Value;

            if (value != MongoDBNull.Value)
            {
                var arrayValue = (keyValue.Value as JArray);
                if (arrayValue != null)
                    value = arrayValue.Select(j => (string)j).ToArray();
            }

            if (document.Contains(keyValue.Key))
                document[keyValue.Key] = value;
            else
            {
                if (value != MongoDBNull.Value)
                    document.Add(keyValue.Key, value);
            }
        }

        return document;
    }
}

Using Castle Dynamic proxy

One implementation left. This time I will use Castle Dynamic proxy to map between Document and Note. I do this by intercepting the properties of Note and store them in a simple statebag. The statebag is then used when converting between Notes and Documents.

First the consuming code that are different than before.

var proxyBuilder = new ProxyBuilder(new ProxyConfig());

//Create and Insert first note
var firstNote = proxyBuilder.ProxyFromClass<Note>(new EntityInterceptor());
firstNote.Title = "First note using Proxies.";
firstNote.Tags = new string[] { "MongoDB", "Getting started" };
firstNote.Body = "Some nice text.";

notes.Insert(firstNote.GetAsDocument());

...

//Create and Insert second note
var secondNote = proxyBuilder.ProxyFromClass<Note>(new EntityInterceptor());
secondNote.Title = "Second note using Proxies.";
secondNote.Body = "Some nice text.";

notes.Insert(secondNote.GetAsDocument());

...

//Read back the second note that lacked tags.
var noteDocument = notes.FindOne(new Document { { "Tags", MongoDBNull.Value } });
var note = proxyBuilder.ProxyFromClass<Note>(new EntityInterceptor());

note.UpdateFromDocument(noteDocument);

note.Tags = new[] { "The tag" };

//Populate the document with the changed C# object, and update in MongoDB.
notes.Update(note.GetAsDocument());

The interceptor that does the work, looks like this.

public class EntityInterceptor
    : IInterceptor
{
    private Dictionary<string, object> _stateBag = new Dictionary<string, object>();
    private static readonly Type _documentType = typeof (Document);

    public void Intercept(IInvocation invocation)
    {
        var name = invocation.MethodInvocationTarget.Name;

        if(IsProperty(name))
        {
            var key = invocation.MethodInvocationTarget.Name.Remove(0, 4);

            if (IsSetter(name))
                SetValue(key, invocation.Arguments[0]);
            else if (IsGetter(name))
            {
                var value = GetValue(key);
                if (value != null)
                    invocation.ReturnValue = value;
            }
        }
        else if(name == "GetAsDocument")
        {
            var document = new Document();

            foreach (var keyValue in _stateBag)
            {
                document.Add(keyValue.Key, keyValue.Value);
            }

            invocation.ReturnValue = document;
        }
        else if (name == "UpdateFromDocument")
            SetValuesFrom((Document)invocation.Arguments[0]);
        else
            invocation.Proceed();
    }

    private void SetValuesFrom(Document document)
    {
        foreach (DictionaryEntry keyValue in document)
            SetValue((string)keyValue.Key, keyValue.Value);
    }

    private void SetValue(string key, object value)
    {
        if(!_stateBag.ContainsKey(key))
            _stateBag.Add(key, value);
        else
            _stateBag[key] = value;
    }

    private object GetValue(string key)
    {
        if (!_stateBag.ContainsKey(key))
            _stateBag.Add(key, null);

        return _stateBag[key];
    }

    private bool IsProperty(string name)
    {
        return (name.StartsWith("set_") || name.StartsWith("get_"));
    }

    private bool IsGetter(string name)
    {
        return name.StartsWith("get_");
    }

    private bool IsSetter(string name)
    {
        return name.StartsWith("set_");
    }
}

That’s it. As always all the code can be downloaded from here.

//Daniel

Use StructureMap and Castle DynamicProxy to easily change the semantics of your code

In this posting my intentions are to show you how to use Inversion of Control (IoC), with the help of StructureMap, for being able to easily switch the semantics of e.g entities in a model with the change of a few lines in the StructureMap configuration. I will use it to go from plain classes to dynamically generated proxies, using Castle DynamicProxy. The proxied version will add the attributes: Serializable and DataContract. I will not implement any interception, but I will setup a empty interceptor which, if you want, you can extend and play with for yourself.

Ok, even if this might not be the most useful scenario (as it was something I fiddled around with) it shows you how easily it is to control your dependencies(when the infrastructure code is in place). E.g. Lets say that I’m using Entity framework 4 (EF4) and the new capabilities of Code-only and POCO entities and I let EF4 generate proxies to keep track of changes etc. I could then instruct StructureMap to let EF4 create the instances for me at all time and not just when I fetch allready persisted entities.

The solution – Pls.ProxyLab

Pls.Core

Contains some simple “reusable” infrastructure code that could be references by all other assemblies.

Pls.ProxyLab.Client

Simple Console application that consumes and outouts some metadata information about the entities.

Pls.ProxyLab.Entities

Contains the entities of the model

Pls.ProxyLab.IoC

Contains the StructureMap-based IoC-container.

Pls.ProxyLab.IoC.Configuration

Contains the congifurations for the StructureMap-based IoC-container. In this demo I have also put the configuration of the ProxyBuilder in this assembly.

The model

To keep things simple I have not included anything else than simple automatic properties and constructors in my entities.

The entity model of the Pls.ProxyLab

A little note about the constructors. As you will se they are only used for initialization of default values and for resolving dependencies between entities. With the use of StructureMap, I actually wouldn’t need the resolving of the other entities, since I could let StructureMap handle this by autowiring dependencies using property setter injection. The reason to why I’m resolving it in the model is that: It shows the intent more clearly and I also couldn’t get StructureMap to handle the dependencies when I was generating proxies.

All members are made virtual so that Castle DynamicProxy can create proxies and intercept the members.

Entity

A simple base class that (when I start incorporating persistancy) will contain implementation for Identity and Concurrency tokens etc. As of right now it’s an empty shell.

public abstract class Entity
{
}

Person, Customer and Room

Simple classes that extends the Entity baseclass with some automatic properties.

public class Person
    : Entity
{
    public virtual string Firstname { get; set; }
    public virtual string Lastname { get; set; }
}
public class Customer
    : Person
{
    public virtual string CustomerNo { get; set; }
}
public class Room
    : Entity
{
    public virtual string RoomNo { get; set; }
}

BookingRequest

Just a little bit more complicated, as it set’s some default values for its members.

public class BookingRequest
    : Entity
{
    public virtual int NoOfAdultBeds { get; set; }
    public virtual int NoOfChildBeds { get; set; }
    public virtual bool SmokingAllowed { get; set; }
    public virtual bool WantsWindow { get; set; }

    public BookingRequest()
    {
        NoOfAdultBeds = 2;
        NoOfChildBeds = 0;
        SmokingAllowed = false;
        WantsWindow = true;
    }
}

Booking

Not so complicated. The only thing that is new is that is resolves some dependencies to other entities.

public class Booking
    : Entity
{
    public virtual BookingRequest Request { get; set; }
    public virtual string BookingNo { get; set; }
    public virtual Customer Customer { get; set; }
    public virtual Room Room { get; set; }

    public Booking()
    {
        Request = EntityFactory.Instance.GetInstance<BookingRequest>();
        Customer = EntityFactory.Instance.GetInstance<Customer>();
        Room = EntityFactory.Instance.GetInstance<Room>();
    }
}

EntityFactory

I have choosen not to talk directly to my IoC-container, but via a simple singleton based EntityFactory, which in turn communicates with the IoC-Container (ProxyLabObjectContainer). I think it gives a more clean naming and understanding of what’s actually being resolved, and I can add a generic constraint so that only entities can be resolved.

public class EntityFactory
{
    public static EntityFactory Instance
    {
        get { return Singleton<EntityFactory>.Instance; }
    }

    public virtual T GetInstance<T>()
        where T : Entity
    {
        return ProxyLabObjectContainer.Instance.GetInstance<T>();
    }
}

Consuming the model

The code for consuming the model is as simple as:

var booking = EntityFactory.Instance.GetInstance<Booking>();

booking.Customer.Firstname = "Daniel";
booking.Customer.Lastname = "Wertheim";
booking.Request.NoOfAdultBeds = 1;
booking.Request.WantsWindow = false;

The StructureMap based IoC-container

The EntityFactory consumed something called ProxyLabObjectContainer which is an IoC-container that uses StructureMap for resolving the objects. The project (Pls.ProxyLab.IoC) only contains one class, the IoC-container, which extends a baseclass from Pls.Core. The only thing it does is to tell StructureMap to look for configurations (in the form of specific StructureMap Registry implementations) in the assembly Pls.ProxyLab.IoC.Configuration, or rather the assemblyname of the assembly containing the IoC-container + .Configurations.

Configuring the IoC-container – Step 1

public class ProxyLabObjectContainer
    : StructureMapObjectContainer
{
    private static string _configurationNamespace 
        = typeof (ProxyLabObjectContainer).Namespace + ".Configuration";

    public static IObjectContainer Instance
    {
        get
        {
            return Singleton<ProxyLabObjectContainer>.Instance;
        }
    }

    protected override void BootstrapContainer()
    {
        Container.Configure(x => x
            .Scan(scanner =>
                      {
                          scanner.Assembly(_configurationNamespace);
                          scanner.LookForRegistries();
                      })
            );
    }
}

Configuring the IoC-container – Step 2

Create a StructureMap Registry implementation that tells the IoC-container how-to resolve the entities. I do this by telling it to scan a specific assembly for all types that extends Entity. I also explicitly exclude the type Entity, since it is abstract and shall not be resolved.

[Serializable]
public class IoCRegistry
    : Registry
{
    public IoCRegistry()
    {
        Scan(s =>
                {
                    s.AssemblyContainingType<Entity>();
                    s.AddAllTypesOf<Entity>();
                    s.ExcludeType<Entity>();
                });
    }
}

Take it for a testride

If we run the application now (which will output information to the console about extended baseclasses, implemented interfaces and attributes) it will not output that much. No interfaces and no attributes, just the baseclass Entity and ultimately System.Object.

Start using proxies instead

Ok, lets pretend I want to use my entities in a WCF scenario, and I want to implement the attributes: Serializable and DataContract. Instead of adding this manually to my classes I will generate proxies for the classes and inject these attributes.

To get acquainted with Castles DynamicProxy (CDP) I have built my own custom API that wraps the funtionality of CDP. All that code is placed in the Pls.Core assembly. I have an interface that defines my custom IProxyBuilder.

ProxyBuilder

public interface IProxyBuilder
{
    IProxyConfig Config { get; set; }

    object ProxyFromClass(Type proxiedClassType, params IInterceptor[] interceptors);

    T ProxyFromClass<T>(params IInterceptor[] interceptors)
        where T : class;

    object ProxyFromInterface(Type proxiedInterfaceType, params IInterceptor[] interceptors);

    T ProxyFromInterface<T>(params IInterceptor[] interceptors)
        where T : class;
}

The intentions are quite clear: A proxybuilder can create proxies using either classes or interfaces as templates. Either using generics or by passing Types. This is only a fraction of all the overloads and possibilities that Castles DynamicProxy (CDP) offers, so my wrapping interface also gives me a cleaner API and therefore, hopefully, offers less confusions.

The implementation that’s included in Pls.Core is really simple and just forwards the calls to CDP’s ProxyGenerator.

public class ProxyBuilder
    : IProxyBuilder
{
    protected virtual ProxyGenerator ProxyGenerator { get; set; }
    public virtual IProxyConfig Config { get; set;}

    public ProxyBuilder(IProxyConfig config)
    {
        ProxyGenerator = new ProxyGenerator();
        Config = config;
    }

    public virtual object ProxyFromClass(Type proxiedClassType, params IInterceptor[] interceptors)
    {
        return ProxyGenerator.CreateClassProxy(
            proxiedClassType, Config.GenerationOptions, interceptors);
    }

    public virtual T ProxyFromClass<T>(params IInterceptor[] interceptors)
        where T : class
    {
        return ProxyGenerator.CreateClassProxy<T>(
            Config.GenerationOptions, interceptors);
    }

    public virtual object ProxyFromInterface(Type proxiedInterfaceType, params IInterceptor[] interceptors)
    {
        return ProxyGenerator.CreateInterfaceProxyWithoutTarget(
            proxiedInterfaceType, Config.GenerationOptions, interceptors);
    }

    public virtual T ProxyFromInterface<T>(params IInterceptor[] interceptors)
        where T : class
    {
        return ProxyGenerator.CreateInterfaceProxyWithoutTarget<T>(
            Config.GenerationOptions, interceptors);
    }
}

Default ProxyConfig

The ProxyBuilder needs some configuration which is provided by injecting an implementation of my custom IProxyConfig interface. I have made a simple default implementation that I will extend when I setup the configurations to use when creating proxies for my entities.

[Serializable]
public class ProxyConfig
    : IProxyConfig
{
    public virtual ProxyGenerationOptions GenerationOptions { get; private set; }

    public ProxyConfig()
    {
        GenerationOptions = new ProxyGenerationOptions();
    }
}

The EntityProxyConfig

The next step is to create a custom ProxyConfig that I will use to instruct an instance of ProxyBuilder, how-to construct proxies for my entities.

    Instructions:

  • Add Serializable attribute
  • Add DataContract attribute

To achieve this I need to create instances of System.Reflection.Emit.CustomAttributeBuilder and inject them to Castles DynamicProxy’s GenerationOptions.

Serializable – CustomAttributeBuilder

Since this attribute doesn’t have any properties or arguments to provide values for, the cTor overload I need to use is:

public CustomAttributeBuilder(
    System.Reflection.ConstructorInfo con,
    object[] constructorArgs)

Which is done in CreateSerializableAttributeBuilder in EntityProxyConfig.

protected virtual CustomAttributeBuilder CreateSerializableAttributeBuilder()
{
    var attributeType = typeof(SerializableAttribute);
    var ctor = attributeType.GetDefaultCtor();

    return new CustomAttributeBuilder(ctor, new object[0]);
}

The GetDefaultCtor is an extensionmethod that you will find in Pls.Core.

DataContract – CustomAttributeBuilder

This attribute has some properties that I want to pass values to, so I need to use another overload of the cTor of CustomAttributeBuilder:

public CustomAttributeBuilder(
    System.Reflection.ConstructorInfo con,
    object[] constructorArgs,
    System.Reflection.PropertyInfo[] namedProperties,
    object[] propertyValues)

So I need to extract PropertyInfos for the properties I want to set values for (namedProperties) and I need to provide values for them (propertyValues).

protected virtual CustomAttributeBuilder CreateDataContractAttributeBuilder()
{
    var attributeType = typeof(DataContractAttribute);
    var ctor = attributeType.GetDefaultCtor();
    var props = GetPropertiesAndValues(attributeType,
                              new Tuple<string, object>(
                                  "IsReference", DataContractTemplate.IsReference),
                              new Tuple<string, object>(
                                  "Namespace", DataContractTemplate.Namespace));

    return new CustomAttributeBuilder(
        ctor, new object[0],
        props.Select(p => p.Item1).ToArray(),
        props.Select(p => p.Item2).ToArray());
}
protected virtual IEnumerable<Tuple<PropertyInfo, object>> GetPropertiesAndValues(
    Type type, params Tuple<string, object>[] nameValues)
{
    return nameValues.Select(
        nameValue => new Tuple<PropertyInfo, object>(
            type.GetProperty(nameValue.Item1), nameValue.Item2)).ToList();
}

A short explanation. I pass simple Tuples with the name of the property I want and the value I want to provide for it:

  • new Tuple(“IsReference”, DataContractTemplate.IsReference)
  • new Tuple(“Namespace”, DataContractTemplate.Namespace)

So I’m obviously interested in specifying two properties: IsReference and Namespace.

I pass these tuples to a simple helper: GetPropertiesAndValues which returns Tuples where the name of the property is replaced with a PropertyInfo. Hence you will get back:

  • Tuple(xxx, true)
  • Tuple(xxx, “MyNamespace.Org”)

Ok, so where does the values “true” and “MyNamespace.Org” comefrom. The being able to affect the configuration I have provided some properties of the EntityProxyConfig. One property is the “DataContractTemplate” which is an simple instance of the DataContractAttribute. I have also provided some other properties that can be configured. The values are now sat in the cTor which probably would lie somewhere else, but this is just a demo so…

public virtual bool ApplySerializable { get; set; }
public virtual bool ApplyDataContract { get; set; }
public virtual DataContractAttribute DataContractTemplate { get; set; }

public EntityProxyConfig()
{
    ApplySerializable = true;
    ApplyDataContract = true;
    DataContractTemplate = new DataContractAttribute { IsReference = true, Namespace = "MyNamespace.org" };

    InitializeProxyGenerationOptions();
}

That is the important code of the EntityProxyConfig-class, the rest is just code that forms a process (chain of method calls and simple instructions) to initialize the GenerationOptions. To complete code for the class looks like this:

[Serializable]
internal class EntityProxyConfig
    : ProxyConfig
{
    public virtual bool ApplySerializable { get; set; }
    public virtual bool ApplyDataContract { get; set; }
    public virtual DataContractAttribute DataContractTemplate { get; set; }

    public EntityProxyConfig()
    {
        ApplySerializable = true;
        ApplyDataContract = true;
        DataContractTemplate = new DataContractAttribute { IsReference = true, Namespace = "MyNamespace.org" };

        InitializeProxyGenerationOptions();
    }

    protected virtual void InitializeProxyGenerationOptions()
    {
        var attributeBuilders = CreateAttributeBuilders();

        foreach (var attributeBuilder in attributeBuilders)
            GenerationOptions.AdditionalAttributes.Add(attributeBuilder);
    }

    protected virtual IEnumerable<CustomAttributeBuilder> CreateAttributeBuilders()
    {
        return new[] { CreateSerializableAttributeBuilder(), CreateDataContractAttributeBuilder() };
    }

    protected virtual CustomAttributeBuilder CreateSerializableAttributeBuilder()
    {
        var attributeType = typeof(SerializableAttribute);
        var ctor = attributeType.GetDefaultCtor();

        return new CustomAttributeBuilder(ctor, new object[0]);
    }

    protected virtual CustomAttributeBuilder CreateDataContractAttributeBuilder()
    {
        var attributeType = typeof(DataContractAttribute);
        var ctor = attributeType.GetDefaultCtor();
        var props = GetPropertiesAndValues(attributeType,
                                  new Tuple<string, object>(
                                      "IsReference", DataContractTemplate.IsReference),
                                  new Tuple<string, object>(
                                      "Namespace", DataContractTemplate.Namespace));

        return new CustomAttributeBuilder(
            ctor, new object[0],
            props.Select(p => p.Item1).ToArray(),
            props.Select(p => p.Item2).ToArray());
    }

    protected virtual IEnumerable<Tuple<PropertyInfo, object>> GetPropertiesAndValues(
        Type type, params Tuple<string, object>[] nameValues)
    {
        return nameValues.Select(
            nameValue => new Tuple<PropertyInfo, object>(
                type.GetProperty(nameValue.Item1), nameValue.Item2)).ToList();
    }
}

Configure StructureMap to use the ProxyBuilder

If I would like to consume the ProxyBuilder without using StructureMap I would use it like this:

var proxyBuilder = new ProxyBuilder(new EntityProxyConfig());
var bookingItem = proxyBuilder.ProxyFromClass<Booking>(new EntityInterceptor());

I will then get a proxied version of my Booking entity and all calls to its virtual members will be intercepted in my custom EntityInterceptor (more about this later).

Remember the IoCRegistry class that scanned the Pls.ProxyLab.Entities assembly for Entity-implementations? We need to add one single line to it, so that we don’t use StructureMaps default convention, but instead our custom EntityConvention, which in turn will specify that the ProxyBuilder should be used.

The line to be added is:

s.Convention<EntityConvention>();

I will also let the IoC-container be responsible of creating my IProxyBuilder implementation as a Singleton:

For<IProxyBuilder>()
    .LifecycleIs(Lifecycles.GetLifecycle(InstanceScope.Singleton))
    .Use<ProxyBuilder>()
    .Named("EntityProxyBuilder")
    .Ctor<IProxyConfig>().Is<EntityProxyConfig>();

So the complete code now looks like this:

[Serializable]
public class IoCRegistry
    : Registry
{
    public IoCRegistry()
    {
        //Add proxybuilder that are used for creation of my entities
        For<IProxyBuilder>()
            .LifecycleIs(Lifecycles.GetLifecycle(InstanceScope.Singleton))
            .Use<ProxyBuilder>()
            .Named("EntityProxyBuilder")
            .Ctor<IProxyConfig>().Is<EntityProxyConfig>();

        //Add all entities
        Scan(s =>
                {
                    s.Convention<EntityConvention>();
                    s.AssemblyContainingType<Entity>();
                    s.AddAllTypesOf<Entity>();
                    s.ExcludeType<Entity>();
                });
    }
}

EntityConvention

Only one thing left to implement, the EntityConvention that will be used to register all the found Entity implementations.

[Serializable]
internal class EntityConvention
    : IRegistrationConvention
{
    public void Process(Type type, Registry registry)
    {
        registry.For(type).Use(
            ctx =>
            {
                var proxyBuilder = ctx.GetInstance<IProxyBuilder>("EntityProxyBuilder");

                return proxyBuilder.ProxyFromClass(type, new EntityInterceptor());
            });
    }
}

I simply use the previously registrered IProxyBuilder for entities and uses it to create a proxied representation of the specific Entity implementation. I provide my custom EntityInterceptor so that I can intercept interactions made to the virtual members of my entities.

The interceptor is currently empty and just lets all calls pass through.

[Serializable]
internal class EntityInterceptor 
    : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        invocation.Proceed();
    }
}

Take it for a testride

Ok, this time the IoC-container will return proxied entities, hence we will get another output.

Proxied entities

As you can see we are now getting proxies of our entities and they have all gained the injected attributes.

That’s it for now. As always you can download the complete code here.

//Daniel