C# is a strongly typed language and while that's a fundamental feature of the language there are more and more situations where dynamic types make a lot of sense. I've written quite a bit about how I use dynamic for creating new type extensions:
Today I want to point out an example of a much simpler usage for dynamic that I use occasionally to get around potential static typing issues in C# code especially those concerning generic types.
TypeCasting Generics
Generic types have been around since .NET 2.0 and they can be extremely useful in creating flexible class designs that are extensible and can deal with different member types/elements. Most of the time they provide great enhancements, but dealing with casting in generics can become very complex especially if there are interdependencies in object.
I've run into a number of situations in the past - especially with generic types that don't implement specific interfaces that can be cast to - where I've been unable to properly cast an object when it's passed to a method or assigned to a property. Granted often this can be a sign of bad design, but in at least some situations the code that needs to be integrated is not under my control so I have to make due with what's available, or the parent object is too complex or intermingled to be easily refactored to a new usage scenario.
Here's an example that I ran into in my own RazorHosting library - so I have really no excuse, but I also don't see another clean way around it in this case.
A Generic Example
Imagine I've implemented a generic type like this:
public class RazorEngine<TBaseTemplateType>
where TBaseTemplateType : RazorTemplateBase, new()
You can now happily instantiate new generic versions of this type with custom template bases or even a non-generic version which is implemented like this:
public class RazorEngine : RazorEngine<RazorTemplateBase>
{
public RazorEngine() : base() { }
}
To instantiate one:
var engine = new RazorEngine<MyCustomRazorTemplate>();
Now imagine that the template class receives a reference to the engine when it's instantiated. This code is fired as part of the Engine pipeline when it gets ready to execute the template. It instantiates the template and assigns itself to the template:
var template = new TBaseTemplateType() {
Engine = this
}
The problem here is that possibly many variations of RazorEngine<T> can be passed to Engine. I can have RazorTemplateBase, RazorFolderHostTemplateBase, CustomRazorTemplateBase etc. as generic parameters and the Engine property has to reflect that somehow. Additionally the generic parameter TBaseTemplateType is in fact the actual active template class. I know what the type is, but not how to declare it on the Engine property to reflect the semi dynamic nature based on inheritance.
So, how would I cast that? My first inclination was to use an interface on the engine class and then cast to the interface. Generally that works, but unfortunately here the engine class is generic and has a few members that require the template type in the member signatures. So while I certainly can implement an interface:
public interface IRazorEngine<TBaseTemplateType>
it doesn't really help for passing this generically templated object to the template class - I still can't cast it if multiple differently typed versions of the generic type could be passed. I have the exact same issue in that I can't specify a 'generic' generic parameter, since there's no underlying base type that's common. Even if I could manage to create a non-generic interface, there are other issues such as instantiation and passing across AppDomain boundaries - this also wouldn't work.
In light of this I decided on using object and the following syntax for the property (and the same would be true for a method parameter):
public class RazorTemplateBase :MarshalByRefObject,IDisposable
{
public object Engine {get;set; }
}
Now because the Engine property is a non-typed object, when I need to do something with this value, I still have no way to cast it explicitly. Specifically the cast needs to be RazorEngine<CurrentRunningClass> which of course doesn't work because that would require a runtime setting.
What I would be nice is:
public RazorEngine<> Engine { get; set; }
but that's not possible.
Dynamic to the Rescue
Luckily with the dynamic type this sort of thing can be mitigated fairly easily.
For example here's a method that uses the Engine property and uses the well known class interface by simply casting the plain object reference to dynamic and then firing away on the properties and methods of the base template class that are common to all templates:
/// <summary>
/// Allows rendering a dynamic template from a string template
/// passing in a model. This is like rendering a partial
/// but providing the input as a
/// </summary>
public virtual string RenderTemplate(string template,object model)
{
if (template == null)
return string.Empty;
// if there's no template markup
if(!template.Contains("@"))
return template;
// use dynamic to get around generic type casting
dynamic engine = Engine;
string result = engine.RenderTemplate(template, model);
if (result == null)
throw new ApplicationException("RenderTemplate failed: " + engine.ErrorMessage);
return result;
}
Prior to .NET 4.0 I would have had to use Reflection for this sort of thing which would have a been a heck of a lot more verbose, but dynamic makes this so much easier and cleaner and in this case at least the overhead is negliable since it's a single dynamic operation on an otherwise very complex operation call.
The point is: To fix this properly with static typing would be complex and require some mental gymnastics around generics. Dynamic provides a very easy workaround to make this work without having to redesign several classes and dependencies.
Dynamic as a Bailout
Sometimes this sort of thing reeks of a design flaw, and I agree that in hindsight this could have been designed differently. But as is often the case this particular scenario wasn't planned for originally and removing the generic signatures from the base type would break a ton of other code in the framework. Given the existing fairly complex engine design, refactoring an interface to remove generic types just to make this particular code work would have been overkill.
Instead dynamic provides a nice and simple and relatively clean solution. Now if there were many other places where this occurs I would probably consider reworking the code to make this cleaner but given this isolated instance and relatively low profile operation use of dynamic seems a valid choice for me.
This solution really works anywhere where you might end up with an inheritance structure that doesn't have a common base or interface that is sufficient. In the example above I know what I'm getting but there's no common base type that I can cast to.
All that said, it's a good idea to think about use of dynamic before you rush in. In many situations there are alternatives that can still work with static typing. Dynamic definitely has some overhead compared to direct static access of objects, so if possible we should definitely stick to static typing.
In the example above the application already uses dynamics extensively for dynamic page page templating and passing models around so introducing dynamics here has very little additional overhead. The operation itself also fires of a fairly resource heavy operation where the overhead of a couple of dynamic member accesses are not a performance issue.
So, what's your experience with dynamic as a bailout mechanism?
Other Posts you might also like