I'm seeking some discussion with this post.
I'm looking at incorporating C# 4.0 Dynamic features into a legacy system. My explicit example is using Rob Connery's Massive in a data layer. But my questions would apply anywhere a dynamic object must interact with an existing, strongly typed business object such that there is a mapping between properties.
I can automate the conversion to and from static (concrete) objects and expando objects with the following two (simplified) methods:
public static object ToConcrete<T>(System.Dynamic.ExpandoObject dynObject)
{
object instance = Activator.CreateInstance<T>();
var dict = dynObject as IDictionary<string, object>;
PropertyInfo[] targetProperties = instance.GetType().GetProperties();
foreach (PropertyInfo property in targetProperties)
{
object propVal;
if (dict.TryGetValue(property.Name, out propVal))
{
property.SetValue(instance, propVal, null);
}
}
return instance;
}
public static System.Dynamic.ExpandoObject ToExpando(object staticObject)
{
System.Dynamic.ExpandoObject expando = new ExpandoObject();
var dict = expando as IDictionary<string, object>;
PropertyInfo[] properties = staticObject.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
dict[property.Name] = property.GetValue(staticObject, null);
}
return expando;
}
But now I have a number of questions.
Does my attempt to span dynamic and non-dynamic in a legacy system represent a misconception on my part? Meaning, am I working against dynamic's intent? Am I setting myself up for problems?
Should my use of dynamics be limited to components that completely contain it with no mapping between dynamic objects and static objects? Meaning, is it bad practice to attempt to mix the two language domains? Am I creating bad architecture? An anti-pattern?
In the case of a component like Massive, if we say it is bad practice to map between ExpandoObject and strongly typed objects, then there is no way I can plug it into my legacy system since it must surface business objects into the legacy code and there is no practical way I can, or should, refactor the objects of a large, legacy code base into dynamic objects. Maybe dynamic can't be realistically added to a legacy .Net code base. Maybe it has to be incorporated from the beginning, or not at all.
So you just want to map statically-typed objects to dynamic objects so they can be used in Massive. I think this is fine, it's like mapping business objects to LINQ to SQL objects so you can work with that ORM. A downside though is that you will end up mapping everything in and out of your database. This can become a pain. It's a pain for me with LINQ to SQL.
Think about what it will be like to change code, and you an measure how effective this approach is. For me, when I need to add a property to a business object, I have to:
This is a pain. Your approach with Massive, if your mapping helpers work correctly, mean you have to do:
That's not bad. Also, how will object graphs be handled? If you have a Person table and an Address table with a 1-M relationship meaning a person can have multiple addresses. How can you query and get a list of people with their addresses? What is your mapping going to look like?
Another approach would be to see if NHibernate or Entity Framework would work in your situation. They are designed to work with statically-typed objects. Massive looks like it's designed for quick and easy data access. Another quick and easy library that is build for statically-typed objects is Dapper. It's easy to use. Check it out on Nuget. Actually, from what I understand of your situation, I'd strongly consider Dapper.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With