Using JSON.Net to eval json into a dynamic variable in C#

So I thought this would be possible and finally decided to give it a shot in 2010 Beta 2. It turns a bunch of JSON into an ExpandoObject using JSON.Net.

Needs cleaning up but not too bad.

        [TestMethod]

        public void DeserializeTestObjectToDynamic(){

            TestObject testObject = new TestObject() {

                FirstName = "Peter",

                LastName = "Goodman",

                DateOfBirth = new DateTime(1979, 2, 3),

                Child = new TestChildObject {

                    Line1 = "child line 1",

                    Line2 = "child line 2",

                    Line3 = "child line 3",

                    City = "child city"

                },

 

                Children = new Collection<TestChildObject>() {

                    new TestChildObject() {

                    Line1 = "children 1 line 1",

                    Line2 = "children 1 line 2",

                    Line3 = "children 1 line 3",

                    City = "children 1 city"

                },

                new TestChildObject() {

                    Line1 = "children 2 line 1",

                    Line2 = "children 2 line 2",

                    Line3 = "children 2 line 3",

                    City = "children 2 city"

                }

                             }

 

            };

 

            // Get our json string

            string json = JsonConvert.SerializeObject(testObject);

 

            // Create the json.Net Linq object for our json string

            JObject jsonObject = JObject.Parse(json);

 

            // eval into an expando

            dynamic dynObject = ConvertJTokenToObject(jsonObject);

 

 

 

            Assert.IsNotNull(dynObject);

 

            Assert.IsNotInstanceOfType(dynObject, typeof(TestObject));

            Assert.IsInstanceOfType(dynObject, typeof(ExpandoObject));

 

            Assert.AreEqual(testObject.FirstName, dynObject.FirstName);

            Assert.AreEqual(testObject.LastName, dynObject.LastName);

            Assert.AreEqual(testObject.DateOfBirth, dynObject.DateOfBirth);

 

            Assert.IsNotNull(dynObject.Child);

            Assert.AreEqual(testObject.Child.Line1, dynObject.Child.Line1);

            Assert.AreEqual(testObject.Child.Line2, dynObject.Child.Line2);

            Assert.AreEqual(testObject.Child.Line3, dynObject.Child.Line3);

 

            Assert.IsNotNull(dynObject.Children);

            Assert.AreEqual(testObject.Children.Count, dynObject.Children.Length);

            for (int i = 0; i < testObject.Children.Count; i++) {

                Assert.AreEqual(testObject.Children[i].Line1, dynObject.Children[i].Line1);

                Assert.AreEqual(testObject.Children[i].Line2, dynObject.Children[i].Line2);

                Assert.AreEqual(testObject.Children[i].Line3, dynObject.Children[i].Line3);

            }

        }

 

        public object ConvertJTokenToObject(JToken token) {

            if (token is JValue) {

                return ((JValue)token).Value;

            }

            if (token is JObject) {

                ExpandoObject expando = new ExpandoObject();

                (from childToken in ((JToken)token) where childToken is JProperty select childToken as JProperty).ToList().ForEach(property => {

                    ((IDictionary<string, object>)expando).Add(property.Name, ConvertJTokenToObject(property.Value));

                });

                return expando;

            }

            if(token is JArray){

                object[] array = new object[((JArray)token).Count];

                int index = 0;

                foreach (JToken arrayItem in ((JArray)token)) {

                    array[index] = ConvertJTokenToObject(arrayItem);

                    index++;

                }

                return array;

            }

            throw new ArgumentException(string.Format("Unknown token type '{0}'", token.GetType()), "token");

        }

 

 

Unit Testing Visual Studio DSL Tools

I’ve been meaning to post this entry for a while now so while I wait for a 2010 beta install to complete….

For a long time I thought it wasn’t possible to unit test DSL Tools projects easily. Due to the nature of the environment it is sometimes difficult to see how unit testing is possible. The model elements are put in a partition in a store and all the partial classes, rules etc are very tightly coupled.

It wasn’t until I wanted to write a use-case oriented management layer on top of our multiple DSLs that I first thought of how it was possible. I wanted to a find way to test that the abstracted co-ordination methods on the management layer would create the expected model elements and what I got was an accidental pattern for testing DSL tools.

The main trick lies in creating a model context that will hold your store, model root and handle transactions.

The ModelingTestContext class:

public class ModelingTestContext : IDisposable {

    private Transaction tx;

    private Store store;

    public ModelingTestContext() {

        store = new Store();

 

        Type domainModelType = typeof(MyCompany.DomainModelDslDomainModel);

 

        // Create a new store to deserialize the instance to.

 

        Type[] metaTypes = new Type[]

                               {

                                   typeof (CoreDesignSurfaceDomainModel),

                                   domainModelType

                               };

        // Load these types into the store, so that it knows about them for deserialization

        store.LoadDomainModels(metaTypes);

 

        tx = store.TransactionManager.BeginTransaction("Domain Modeling Test Context");

        domainModelRoot = new MyModelRoot(store);

    }

 

 

    public MyModelRoot DomainModelRoot {

        get { return domainModelRoot; }

    }

 

    public Store Store {

        get { return store; }

    }

 

    public void CommitChanges() {

        tx.Commit();

        tx = store.TransactionManager.BeginTransaction("Domain Modeling Test Context");

    }

 

    public void Dispose() {

        if(tx != null && tx.IsActive) {

            tx.Rollback();

        }

    }

}

This class will create the model root inside the store and manage transactions for us. We next need to start writing a test.

[TestMethod]

public void CreateAssociationSingleMultiplicity() {

    using (ModelingTestContext domainContext = new ModelingTestContext()) {

        domainContext.DomainModelRoot.Namespace = "Aderant.Test.DomainFoo";

 

        DomainComponent clientDc = domainContext.CreateDomainComponent("Client");

 

        DomainComponent addressDc = domainContext.CreateDomainComponent("Address");

 

        AssociationLink link = clientDc.AssociateWith(addressDc, Multiplicity.One);

 

 

        domainContext.CommitChanges();

        Assert.AreEqual(addressDc.Name, link.TargetRoleName);

 

    }

}

We create a context inside a using block so that we can clean up the transaction when the test completes. In this test I have added extension methods to the domain context and the DomainComponent class to support the common scenarios I used in testing like CreateDomainComponent and AssociationWith, allowing me to encapsulate common behavior. These extension methods can then be moved to become behavior of the model or the management API. Therefore over time you provide better API functionality which is tested.

Now some people would call this integration testing instead of unit testing…..fair enough. Also some would say that the extension methods and the test context for that matter are making the tests brittle as DRY does not apply to unit testing, I would disagree as otherwise these tests would become unmanageable.

I hope you find this useful.

Pete

Don’t try to explain geek jokes to your partner

 

I tried to explain the humour in this joke to my girlfriend. I was laughing too hard at the time, partly at the joke, partly at the fact I was trying to explain it to her. Don’t try this at home, it may make you a very lonely person.

Shizxaml – Silverlight’s old codename?

According to Mike Harsh in his Mix talk on Silverlight 3.0 – Out of Browser, before silverlight was WPF/E, internally Microsoft were calling it Shizxaml. I so wish this had been the product name. “Lets shizxaml that sucker” and the like. Brilliant!

DataContractJsonSerializer and DateTime values

In using the DataContractJsonSerializer beware of DateTime instances which have been instantiated as non-UTC. If you declare without explicitly assigning a DateTime you get the same as default(DateTime), this is 01/01/01 00:00:00 (0 ticks) with a DateTimeKind of Unspecified. When the DataContractJsonSerializer looks at this value (or a Local datetime), it will try to convert it to UTC by subtracting the time zone ala UTC standard notation, this results in a date time that is less that 0 ticks and an out of range exception if you are west of GMT.

The solution is to always instantiate as UTC and you can avoid this issue. As mentioned previously you cannot interrupt the serialization process for DateTime on a member of the DataContract serializer family.

Another pain in the rectum is that it will change the accuracy of your DateTime value from 100 ns to 1 ms, so if you are relying on this value being the same for change tracking or any other means then this will produce problems.

WCF Collections with Payload via Surrogates

Previously I posted about the problem with WCF and collection which have a payload in them. I came across this problem again when using the DataContractJsonSerializer and thought I would look at possibilities to resolve it.

If you have implemented the IXmlSerializable interface then you are kind of stuffed because the Json serializer will emit json with a bunch of xml in the middle….nice! It is really useful to reference sowmy’s post on the precedence of serializable classes in the Data Contract family of serializers.

Instead you can use a Surrogate. This is a class which implements IDataContractSurrogate and can be passed to the constructor of the serializer. It tells the serializer that when you come to serialize type x, instead use type y and I will give you the converted instance. At the other end the class gets deserialized into the original type and all is good.

For our custom collection with payload this works great. It will not however work with CLR types like DateTime, the precedence of WCF serialization kicks in before the surrogate provider is queried for a transmission type.

MS-Test DeploymentItem Attribute........Aaaaaaaagh!

We have a policy of using MS-Test, although that is overdue for a serious review.

So it turns out you can use the deployment item attribute....

[TestMethod]

[DeploymentItem("UnitTest.MyProject.TestData.xml")]

public void GetAllStatuses() {...}

....As long as you don’t provide a constant...

public const string XMLCONFIGFILE = "UnitTest.MyProject.TestData.xml";

[TestMethod]

[DeploymentItem(TestHelper.XMLCONFIGFILE)]

public void GetAllStatuses() {...}

It just ignores it.....Genius! Now my tests have to be littered with this string literal.

Makes you wonder how they are implementing this stuff.

Pete

C# var - with great power comes great responsibility

There are many heated discussions on the overuse of var and I'm not going to repeat the arguments here. Personally, I have no problem with var used in the declaration of a variable where the value is instantiated inline via a constructor, anything else (apart from LINQ) seems dangerous. Having said that, the following sample I came across today is simply stupid.

var controller = new MyController().GetValueX(foo);

Preview Handlers for Vista and Outlook 2007

Really useful for those xml files that people send you.

Download the MSDN Magazine Preview Handlers and then setup the xml file with this really cool utility. It gives explorer and outlook preview capabilities for all sorts of file types.

DSL Tools in Visual Studio 2010

Stuart Kent has blogged about the new features they are planning for DSL Tools in the Visual Studio 2010 timeframe. Of particular interest are:

  • Dsl extensibility. Extend the domain model and behavior for a DSL after it's been deployed, including DSLs shipped by a third party.

  • Readonly. Selectively switch off the ability to edit models and model elements in a designer.

  • Forms-based UI. Easily bind models to winforms and WPF-based forms UI. IMS now implements the necessary databinding interfaces.

  • Modelbus. A new piece of platform to support cross-referencing between models and interaction between designers. This has been one of customers' main requests. This one kind of blows my codeplex project out of the water, which is probably a good thing as I can't find the time to finish it.

  • T4 precompile. Precompile text templates so that they can be deployed for use on machines that do not have VS installed.

Also of interest are the various blog entries on the overlap between DSL and Oslo from Stuart Kent and Keith Short. Personally I think Oslo is a huge step forward for Model-Driven architectures and shows a willingness to provide something useful for developers which does more than simply expand the already disparate tooling.