Daniel Wertheim

Love what you do – Continue to do it – Be ager to learn more about it.

My opinion on mappings for MongoDB

leave a comment »

I think that enforcing mappings when using MongoDb is like taking a step towards an OR/M instead of away from it, and in my opinion: away is better. A strength with MongoDB is that it’s schema less, why then add fictive schemas by adding mappings in your C# code?

The driver I’m building uses Json.Net so that I can serialize/deserialize objects (anonymous types, static types, JSON-strings) back and forth between the DB and my conceptual model.

If you are using Sam Corders more mature C#-driver you migth wan’t to look at my earlier writings to get rid of manual mappings. You might also want to checkout Automapper to handle mappings with Dictionaries.

http://daniel.wertheim.se/2010/02/05/getting-started-with-mongodb-using-json-net-and-castle-dynamic-proxy/
http://daniel.wertheim.se/2010/02/07/mongodb-in-c-extensions-to-support-json-mapping-or-proxy-generation/
http://automapper.codeplex.com/

//Daniel

Written by Daniel Wertheim

2010/03/06 at 19:50

Simple-MongoDb – Just added support for generating ObjectId’s

leave a comment »

As I’m working on adding support for DbReferences I added support for dealing with ObjectId’s in your typed classes. You can still skip them if you want, and instead rely on the database for the generation.

Note! I’m working against the MongoDB v.1.2.4 and not 1.3.x. I tested it against the later and got some strange results in my tests, so for now (during the implementation of DbRef) I will use v.1.2.4 and after that I will get it to work against v.1.3.x

So some short code examples of the ObjectId. First the new static factory method: SimoObjectId.NewId(). It generates a ObjectId according to specs (http://www.mongodb.org/display/DOCS/Object+IDs)

[TestMethod]
public void Insert_TypedDocumentWithAssignedId_IsStored()
{
    var document = new PersonWithId { _id = SimoObjectId.NewId(), Name = "Daniel" };

    using (var session = new SimoSession(CreateConnection()))
    {
        session[DbName][PersonsCollectionName].Insert(document);
    }

    var numOfDocs = GetDocumentCount(new { _id = document._id }, Constants.Commands.PersonsFullCollectionName);
    Assert.AreEqual(1, numOfDocs);
}

[Serializable]
public class PersonWithId
    : Person
{
    public virtual SimoObjectId _id { get; set; }
}

If you don’t want to call SimoObjectId.NewId() each time and you don’t want to add this in the constructor, there’s a simple alternative: the SimoAutoObjectId.

[TestMethod]
public void Insert_TypedDocumentWithAutoAssignedId_IsStored()
{
    var document = new PersonWithAutoId { Name = "Daniel" };

    using (var session = new SimoSession(CreateConnection()))
    {
        session[DbName][PersonsCollectionName].Insert(document);
    }

    var numOfDocs = GetDocumentCount(new { _id = document._id }, Constants.Commands.PersonsFullCollectionName);
    Assert.AreEqual(1, numOfDocs);
}

[Serializable]
public class PersonWithAutoId
    : Person
{
    private SimoAutoObjectId _simoAutoObjectId = new SimoAutoObjectId();

    public virtual SimoObjectId _id
    {
        get { return _simoAutoObjectId; }
        set { _simoAutoObjectId = value; }
    }
}

Of, course you then can’t rely on auto.properties anymore.

That’s it. The next time I hope I will wright about DbRef-support.

The source code as well as ZIP is available at: http://code.google.com/p/simple-mongodb/

//Daniel

Written by Daniel Wertheim

2010/03/05 at 01:41

Simple-MongoDB – Alpha version is out

with 2 comments

Ok, it’s finally out. My driver agains MongoDB can be downloaded from: http://code.google.com/p/simple-mongodb/

I will try to write more about how to use it, in the next couple of days, but for now I will just double post the info that’s posted on the Google code site.

A C# implementation of a driver that can be used to communicate with MongoDB. The focus lies in keeping it “dynamic” by using anonymous types and JSON.

  • No need of extending a certain base-class.
  • No need for mappings.
  • No need for using key-value dictionaries, it’s up to you
  • Does relly on Db for Id-generation (the Id is for the Db, you should focus on business keys)
  • Using a well known JSON/BSON-serializer (http://james.newtonking.com/projects/json-net.aspx).

    Roadmap

  • Authorization
  • DbRef
  • Grid
  • Simplify Querying
  • RegularExpressions
  • Documentation
  • API

    The API comes in two flavours: one where you directly consume commandobjects (insert, update, delete, query);and one where this is abstracted away, where you instead use a session with hierarchies.

    Some simple examples of how the API currently looks like (it’s an alpha release so the API will probably have some changes).

    Connection

    To work with Simple-MongoDb you need to establish a connection to a MongoDb-server. This is done by creating an instance of SimoConnection (simo = Simple-MongoDb). The SimoConnection needs to know: address and port of the server. This is wrapped in SimoConnectionInfo, which could be populated manually or via connectionstring-name:

    var cn = new SimoConnection(new SimoConnectionInfo(Constants.ConnectionStringName));
    
    <connectionStrings>
      <add name="SimpleMongoDbTests" connectionString="host:localhost;port:27017"/>
    </connectionStrings>
    

    Below I have wrapped this in a factory-method CreateConnection().

    Commands

    var document = new { Name = "Daniel", Age = 29 };
    
    using (var cn = CreateConnection())
    {
        var insertCommand = new InsertDocumentsCommand(cn)
        {
            FullCollectionName = "TestDb.Persons",
            Documents = new[] { document }
        };
        insertCommand.Execute();
    }
    

    Session

    var document = new { Name = "Daniel", Age = 29 };
    
    using (var session = new SimoSession(CreateConnection()))
    {
        session["TestDb"]["Persons"].Insert(document);
    }
    

    Querying could be done in a numerous ways(not yet regexs, it’s on the roadmap).

  • Json: var query = @"{Age : 29}"
  • Json: var query = @"{$where: ""this.Name == 'Daniel' && this.Age == 29""}"
  • Anonymous type: var query = new {Name = "Daniel"}
  • Typed: var query = new Person {Name = "Daniel"}
  • WhereOperator: See below
  • using (var session = new SimoSession(CreateConnection()))
    {
        var persons = session[DbName][PersonsCollectionName]
            .Find<Person>(new WhereOperator("this.Age > 20 && this.Age < 65"));
    }
    

    //Daniel

    Written by Daniel Wertheim

    2010/03/02 at 10:48

    Simple-MongoDB, Open source C#-driver

    leave a comment »

    Hi!

    As I posted about earlier today, I have started building my own driver against MongoDB, using C#. I’m striving against keeping it Json-centric. What I mean by this is that I rely on Json for serializing objects, so that you can use both static C# types as well as anonymous types or key-values.

    The project home is for now hosted on Google-code: http://code.google.com/p/simple-mongodb/

    There is some sample code (which is from working code) to look at, but yet nothing to download. Hopefully I will have something up during this weekend.

    //Daniel

    Written by Daniel Wertheim

    2010/02/19 at 22:12

    C# driver for MongoDB

    with 2 comments

    I have started to build my own driver against MongoDb, where I’m using Newtonsofts-Json-library for dealing with JSON and BSON serialization.

    It will be open source.

    The first draft of how you can insert documents looks like this:

    [Serializable]
    public class Person
        : MongoDocument
    {
        public virtual string Name { get; set; }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            //Example 1 - Using Connection and manually configured default ConnectionInfo
            using (var cn = new MongoConnection(new ConnectionInfo("localhost", 27017)))
            {
                var cmd = new InsertDocumentsCommand(cn);
                cmd.FullCollectionName = "MyDb1.MyCol1";
                cmd.Documents = new[] { new Person { Name = "Daniel" } };
                cmd.Execute();
            }
    
            //Example 2 - Using Session, with DefaultConnection.
            using (var session = new MongoSession(new MongoConnection(ConnectionInfo.Default)))
            {
                session["MyDb2"]["MyCol2"].Insert(new Person { Name = "Daniel" });
            }
    
            //Example 3 - Using Session, using connectionstring-settings from app.config
            using (var session = new MongoSession(new MongoConnection(new ConnectionInfo("MongoDBServer"))))
            {
                session["MyDb3"]["MyCol3"].Insert(new Person { Name = "Daniel" });
            }
            //var dynamic = new DynamicDocument(@"{Name:""Daniel""}");
        }
    }
    

    The MongoDocument that is being extended in Person has no komplexity at all. It just provides the MongoDB _id-bag.

    [Serializable]
    public abstract class MongoDocument
        : IMongoDocument
    {
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string _id { get; set; }
    }
    

    I will include the functionality from my earlier writings on this topic, to deal with dynamic-documents (JSON).

    //Daniel

    Written by Daniel Wertheim

    2010/02/19 at 08:56

    Where are your Scenarios in your domain?

    with 2 comments

    If you design your entities before you design your scenarios, you are data-driven! The Scenarios are primary – The entities are secondary!

    - Daniel Wertheim

    My words of what I think is wrong in many projects, and thats what this post is about.

    Definition of Scenario

    a postulated sequence of possible events

    - http://wordnetweb.princeton.edu/perl/webwn?s=scenario

    In computing, a scenario is a narrative describing foreseeable interactions of types of users (characters) and the system. Scenarios include information about goals, expectations, motivations, actions and reactions. Scenarios are neither predictions nor forecasts, but rather attempts to reflect on or portray the way in which a system is used in the context of daily activity.

    http://en.wikipedia.org/wiki/Scenario_(computing)

    I tend to bump into situations where I meet people that are proclaiming they are adapting DDD in their projects and that they are writing object-oriented systems. As I’m always interested in learning, I fire of a couple of questions about what they mean by DDD and OO. I will not bother you with the dialog, but will rather skip to a summarize of the conversation. and present five of the artifacts that they think significates that they are conforming to DDD which I think is well worth to notice and discuss about:

  • They are object-oriented
    Meaning “that they are not using datasets anymore to keep track of the state and simple validation.”
  • They have POCO entities
    Meaning “that they have an OR/M that to some extent hides some of the artifacts of dealing with persisting the entities.”
  • They have repositories
    Meaning “there’s at least one repository per aggregate root (most often more), dealing with CRUDs.”
  • They have domain-services
    Meaning “they have some objects named [Entity][Service/Manager] which contains logic and calls to repositories”.
  • They have a model
    Meaning “they have a bunch of the above objects collaborating together”.
  • Ok, so I have designed system like these to. I will probably do it again. But lets look at what I mean by “systems like these” and what I think is wrong.

    Whats wrong?
    So I think we tend to create a model with an emphasis on entities, which more or less becomes a representation of tables in a traditional database. I like to define these entities as “an intelligent data-row” and by intelligent I mean that it might have simple validation of state and some logic for aggregating values, e.g. “Sum of the contained order lines in the order”. Furthermore we tend to create a bunch of services/managers that is named: “[Entity][Service/Manager]“; which to some extent holds together the flow – which most often means, they do some simple validation/rule-evaluation and they interact with a repository. I think these Services/Manager-classes arise from a mental mind of the developer looking like this: “The entity must be POCO and can’t have anything to do with persisting entities. I’ll just create a service that calls the repository and since I’m working with my order-entity, I’ll name it “OrderService”.

    Again, we end up here because we are thinking objects and state and how the objects correlate to each other. And when sitting there, performing TDD with a shallow understanding of the domain; it’s probably the easiest way to get started. Classic example: “Customer places a new order” => “OrderService.PlacerOrder” which receives an order entity with some contained lines and a customer. So my question to you then is: “What exactly is OrderService in the business”? If it is the customer that makes the request, why can’t it be “Customer.PlaceNewOrder”? Or a domain-object named something that mimics the scenario/process, e.g.: “PlaceNewOrder” or “OrderRegistration”.

    To sum it all up: The scenarios/processes in the domain is the core of the business. It’s what make the business unique and is what they are competing with against other competitors. This is what should drive your design. Without a fair understanding of the domain you will risk, getting data centric. The Domain should drive the design of your model, not TDD. Get a deep knowledge of the business and it’s processes and not only the binary rules and the state. These are the aspects that should be reflected in your code.

    //Daniel

    Written by Daniel Wertheim

    2010/02/11 at 22:33

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

    with 2 comments

    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

    Written by Daniel Wertheim

    2010/02/07 at 14:17

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

    with 14 comments

    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! See new post.

    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

    Written by Daniel Wertheim

    2010/02/05 at 15:30

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

    with one comment

    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

    Written by Daniel Wertheim

    2010/01/22 at 12:31

    How-to isolate DateTime.Now in your unit tests

    with one comment

    Updated: The code for the OverrideDateTimeWithQueue method and the test that consumed it has been updated.

    I’m currently working on an application that makes some calculations depending on dates. In one scenario I wanted to ensure that a correct timeintervall is created from DateTime.Now. Since I’m not using TypeMock an easy way is to don’t access DateTime.Now directly in my code, but via instead via a static proxy, to which I can inject code that tells it what dates to return. This is not a new solution, search with Google for eg. “unit test datetime.now” and see for your self.

    I also wanted the ability to Queue dates, for the ability to setup a range of expected dates that would be dequeued at each requested for DateTime.Now. One simple implementation I could think of was to let my static proxy implementation use a Func that per default just returns DateTime.Now; but of course can be overridden by the user.

    Before we look at the tests, lets give some insight to the domain: With the use of a recorder I can create recordings. Each recording will get a start- and stoptime and will be created when recorder.Stop is invoked. The Recording can then be fetched/accessed via recorder.LastRecording or via an event: RecordingCompleted; raised by the recorder. The Recorder holds StartedAt and StoppedAt timestamps which are used to populate the Recording.

    When I want the value of DateTime.Now in my domain, I fetch it from my proxy: DateTimeNow.Value

    The Old test

    [TestMethod]
    public void Start_WhenSecondCall_TimeStampsAreUpdated()
    {
    	var recorder = RecorderFactoryForTests.Default();
    	recorder.Start();
    	recorder.Stop();
    
    	DateTimeAsserts.GainsValueBetweenNow(
    		() => recorder.StartedAt, recorder.Start);
    	Assert.IsNull(recorder.StoppedAt);
    }
    

    DateTimeAsserts.GainsValueBetweenNow, ensures that when recorder.Start is invoked a before and after timestamp is stored away and then is the recorder.StartedAt compared against these dates. Not so good, since I can’t isolate the value.

    The New test

    [TestMethod]
    public void Start_WhenSecondCall_TimeStampsAreUpdated()
    {
        var dateTimes = new[] {
                DateTime.Parse("2010-01-01 00:00:00"),
                DateTime.Parse("2010-01-01 00:01:00"),
                DateTime.Parse("2010-01-01 00:02:00") };
        var recorder = RecorderFactoryForTests.Default();
    
        TestHelper.OverrideDateTimeWithQueue(
            () =>
            {
                recorder.Start();
                recorder.Stop();
                recorder.Start();
            }, dateTimes);
    
        Assert.AreEqual(dateTimes[2], recorder.StartedAt);
        Assert.IsNull(recorder.StoppedAt);
    }
    

    Now, the first item in dateTimes will be consumed by recorder.Start() and assigned to recorder.StartedAt. The second element will be assigned to StoppedAt in recorder.Stop() and the last value will be assigned to recorder.StartedAt when the last recorder.Start() call is executed.

    The test will of course break if let’s say the first call to recorder.Start() invokes DateTimeNow.Value two times. Another way to write the test is:

    [TestMethod]
    public void Start_WhenSecondCall_TimeStampsAreUpdated()
    {
        var expectedStartedAt = DateTime.Parse("2010-01-01 00:02:00");
        var recorder = RecorderFactoryForTests.Default();
    
        recorder.Start();
        recorder.Stop();
    
        DateTimeNow.Set(() => expectedStartedAt);
        recorder.Start();
    
        Assert.AreEqual(expectedStartedAt, recorder.StartedAt);
        Assert.IsNull(recorder.StoppedAt);
    }
    

    Code for DateTimeNow

    public static class DateTimeNow
    {
        private static readonly object _lock;
        private static Func<DateTime> DateTimeNowFunc { get; set; }
    
        static DateTimeNow()
        {
            _lock = new object();
            Reset();
        }
    
        public static DateTime Value
        {
            get { return DateTimeNowFunc.Invoke(); }
        }
    
        public static void Set(Func<DateTime> dateTimeNowFunc)
        {
            lock (_lock)
            {
                DateTimeNowFunc = dateTimeNowFunc;
            }
        }
    
        public static void Reset()
        {
            Set(() => DateTime.Now);
        }
    }
    

    Code for the TestHelper.OverrideDateTimeWithQueue

    public static void OverrideDateTimeWithQueue(Action action, params DateTime[] expectedDates)
    {
        var queuedDates = new Queue<DateTime>(expectedDates);
    
        try
        {
            DateTimeNow.Set(queuedDates.Dequeue);
            action.Invoke();
        }
        finally
        {
            DateTimeNow.Reset();
        }
    }
    

    That’s it.

    //Daniel

    Written by Daniel Wertheim

    2010/01/17 at 13:40

    Posted in Testing

    Tagged with