<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Deserialized &#187; dotnet</title>
	<atom:link href="http://deserialized.com/tag/dotnet/feed/" rel="self" type="application/rss+xml" />
	<link>http://deserialized.com</link>
	<description>The Ramblings of a Web Architect</description>
	<lastBuildDate>Mon, 23 Jan 2012 16:33:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Convert C# classes to and from MongoDB Documents automatically using .NET reflection</title>
		<link>http://deserialized.com/c-sharp/convert-csharp-classes-to-and-from-mongodb-documents-automatically-using-net-reflection/</link>
		<comments>http://deserialized.com/c-sharp/convert-csharp-classes-to-and-from-mongodb-documents-automatically-using-net-reflection/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 15:47:23 +0000</pubDate>
		<dc:creator>Bryan Migliorisi</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[mongo]]></category>

		<guid isPermaLink="false">http://deserialized.com/?p=53</guid>
		<description><![CDATA[There are a number of C# based MongoDB projects being actively developed right now but one thing that I needed was a way to convert a standard C# class to a MongoDB document for easy insertion.&#160; It isn't hard to manually type out and set each property by hand, but it certainly is not the [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fdeserialized.com%2Fc-sharp%2Fconvert-csharp-classes-to-and-from-mongodb-documents-automatically-using-net-reflection%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fdeserialized.com%2Fc-sharp%2Fconvert-csharp-classes-to-and-from-mongodb-documents-automatically-using-net-reflection%2F&amp;source=Deserialized&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>There are a <a href="http://deserialized.com/the-state-of-mongodb-and-csharp/">number of C# based MongoDB projects</a> being actively developed right now but one thing that I needed was a way to convert a standard C# class to a <a href="http://www.mongodb.com">MongoDB</a> document for easy insertion.&#160; It isn't hard to manually type out and set each property by hand, but it certainly is not the most efficient way, especially when you know you are going to be doing it a lot.</p>
<p>&#160;</p>
<p>For example:</p>
<p>Lets say I have a class called <em>SomeClass</em> that looks something like this:</p>
<pre class="brush: csharp">class SomeClass {
	public string StringTest;
	public int IntTest;
}</pre>
<p>And somewhere in my code, I have an instance of this class named <em>someClassInstance</em>.&#160; If I want to create a MongoDB document from this class, I’d have to do something like this:</p>
<pre class="brush: csharp">Document document = new Document();
document.add('StringTest', someClassInstance.StringTest);
document.add('IntTest', someClassInstance.IntTest);</pre>
<p>So that isn't such a big deal, right? But what about when I have a class with many more properties?&#160; Then it starts to get messy and cumbersome.&#160; I thought that there should be an straightforward way to easily convert any class to a mongo-csharp compatible Document object. (I am using <a href="http://twitter.com/samcorder">Sam Corder’s</a> <a href="http://github.com/samus/mongodb-csharp">mongo-csharp driver</a>, so that I am targeting the Document object from that library.)</p>
<h3>Default values</h3>
<p>I also wanted to have a way to specify what the default values were for each class property so that when we did the conversion, we would (hopefully) not end up with any null values.&#160; Plus, if for some reason there was a document in MongoDB that was missing a particular key-value pair, the DocumentConverter would automatically fill in that empty field with the default value so in the code we should never have any nulls.</p>
<p>This is something that I would like for my own purposes and may not suit everyone’s needs.&#160; If it doesn't, simply leave off the DefaultValueAttribute and you’ll never know the difference.</p>
<h3>My proposed solution</h3>
<p>I figured the easiest way to accomplish this was to create a class that would encapsulate all the functionality needed to convert to and from Document objects and have my other classes inherit from that one. I imagined that the above code would change to something like this:</p>
<pre class="brush: csharp">class SomeClass : DocumentConverter {
	[Attributes.DefaultValue(&quot;Default StringTest value!&quot;)]
	public string StringTest;
	[Attributes.DefaultValue(16)]
	public int IntTest;
}</pre>
<p>And to do the conversion would be very simple.&#160; To convert from <em>someClass</em> to <em>Document</em> would be:</p>
<pre class="brush: csharp">Document document = someClassInstance.ToMongoDocument();</pre>
<p>To convert from a <em>Document</em> object to <em>someClass</em> would be:</p>
<pre class="brush: csharp">SomeClass someOtherClassInstance = new SomeClass();
omeOtherClassInstance .FromMongoDocument(someDocumentObject);</pre>
<h3>The DefaultAttribute class</h3>
<pre class="brush: csharp">using System;
namespace MyApp.Attributes
{
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
    class DefaultValueAttribute : Attribute
    {
        private readonly object _value;

        public DefaultValueAttribute(object Value)
        {
            _value = Value;
        }

        public object GetDefaultValue()
        {
            return _value;
        }
    }
}</pre>
<h3>The DocumentConverter class</h3>
<p>Reflection isn't something that I use too often so there may be better ways of accomplishing what I am trying to do, but this is what I’ve got for now.&#160; If there are better ways, please let me know.&#160; Without further ado…</p>
<pre class="brush: csharp">using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using MyApp.Classes.Attributes;
using MongoDB.Driver;

namespace MyApp.Classes
{
    public class DocumentConverter
    {
        public void FromMongoDocument(Document document)
        {
            foreach (DictionaryEntry kvp in document)
            {
                object propertyValue;
                if (kvp.Value != null &amp;&amp; (kvp.Value.GetType() == typeof(Document)))
                {
                    // We have a document object - Now lets get a reference to the class property's type
                    var propertyType = GetType().GetProperty(kvp.Key.ToString()).PropertyType;

                    // create new instance of that class
                    var propertyInstance = Activator.CreateInstance(propertyType);

                    // call FromMongoDocument on that class and pass in the document
                    MethodInfo method = propertyInstance.GetType().GetMethod(&quot;FromMongoDocument&quot;);
                    method.Invoke(propertyInstance, new[] { kvp.Value });

                    propertyValue = propertyInstance;
                }
                else
                {
                    // This is not a Document so lets just assign the value
                    propertyValue = kvp.Value;
                }

                GetType().GetProperty(kvp.Key.ToString()).SetValue(this, propertyValue, null);
            }

        }

        public Document ToMongoDocument()
        {
            Document document = new Document();

            foreach (PropertyInfo property in GetType().GetProperties())
            {
                // Get the value of this property
                object propertyValue = property.GetValue(this, null);

                // If this value is null, then lets try to see if there is a default value attribute and assign that
                if (propertyValue == null)
                {
                    object[] attributes = property.GetCustomAttributes(typeof(DefaultValueAttribute), true);
                    foreach (DefaultValueAttribute defaultValue in attributes.Cast<defaultvalueattribute>())
                    {
                        propertyValue = defaultValue.GetDefaultValue();
                    }
                    document.Add(property.Name, propertyValue);
                }
                else
                {
                    // We have a property, now lets see if this property has a ToMongoDocument method
                    MethodInfo method = propertyValue.GetType().GetMethod(&quot;ToMongoDocument&quot;);

                    if (method == null)
                    {
                        document.Add(property.Name, property.GetValue(this, null));
                    }
                    else
                    {
                        document.Add(property.Name, method.Invoke(propertyValue, null));
                    }
                }
            }
            return document;
        }
    }
}</pre>
<h3>That’s all for now</h3>
<p>I hope this is useful for someone.&#160; It is a rough draft of what I threw together last night at around 1AM while half asleep.&#160; So far, it has passed all of my initial tests but if you have suggestions to make it better, please leave some comments here. </p>
]]></content:encoded>
			<wfw:commentRss>http://deserialized.com/c-sharp/convert-csharp-classes-to-and-from-mongodb-documents-automatically-using-net-reflection/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

