Dynamic Code for type casting Generic Types 'generically' in C#

Posted by Rick Strahl on West-Wind See other posts from West-Wind or by Rick Strahl
Published on Tue, 23 Oct 2012 09:06:26 GMT Indexed on 2012/10/23 11:01 UTC
Read the original article Hit count: 573

Filed under:

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

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. I can have RazorTemplateBase, RazorFolderHostTemplateBase, CustomRazorTemplateBase etc. as generic parameters and the Engine property has to reflect that somehow.

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.

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.

What I really would need 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.

Dynamic as  a Bailout

Sometimes this sort of thing often 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?

© Rick Strahl, West Wind Technologies, 2005-2012
Posted in CSharp  

© West-Wind or respective owner

Related posts about CSharp