Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

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


:P
On this page:

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?

Posted in CSharp  

The Voices of Reason


 

Brian
October 23, 2012

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

I was REALLY looking forward to your talk at DevConnections about "Hosting the Razor Scripting Engine in Your Own Applications", but it turns out that I can't attend that. Will you be going to the DevIntersection conference? Is there a chance that you can post a video/slides/sample code later on?

Regardless, you've always provided valuable info on your blog....Thanks.

Robert
October 23, 2012

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

You said

> What I really would need is:
public RazorEngine<> Engine { get; set; } 

> but that's not possible.


could you explain why you can't just make this
public RazorEngine<TBaseTemplateType> Engine { get; set; } 

thanks

Rick Strahl
October 23, 2012

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

@Robert - Unfortunately the problem is two fold: a) The template class isn't generic so it doesn't have a TBaseTemplateType type to assign to the engine and more importantly b) The template type *is* the actual executing class which typically will be a subclass of the Base template class. Each application has its own template implementation and so the template type is different for each implementation.

So the Engine is of type RazorEngine<'ThisClass'> which I'm not sure how it could be expressed as a generic expression, because ThisClass would have to be determined at runtime, not compile time as it reflects the active inherited class. Unfortunately generic parameters don't inherit so RazorEngine<RazorTemplateBase> won't cast RazorEngine<CustomTemplate> either even though the template parameters are derived from each other.

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.

Rick Strahl
October 23, 2012

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

@Brian - Yes I'm going and talking on hosting the Razor Engine and will post the code and slides when the show's over.

However the RazorHost classes that I'll be discussing are available already and you can download them from GitHub and NuGet: https://github.com/RickStrahl/Westwind.RazorHosting

Caco
October 24, 2012

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

Would a construction like this work for you, instead of the dynamic?

public interface IRazorEngine
{
     string RenderTemplate(string template, object model);
     string ErrorMessage { get; }
}
 
public abstract class RazorEngine<TBaseTemplateType> : IRazorEngine
    where TBaseTemplateType : RazorTemplateBase, new()
{
     public string RenderTemplate(string template, object model)
     {
         return RenderTemplate(template, (TBaseTemplateType)model);
     }
 
     public abstract string ErrorMessage { get; }
 
     protected abstract string RenderTemplate(string template, TBaseTemplateType model);
}


Then in a class where you need it, you only need a IRazorEngine:
public class CustomEngine : RazorEngine<RazorTemplateBase>
{
    protected override string RenderTemplate(string template, RazorTemplateBase model)
    {
        throw new NotImplementedException();
    }
 
    public override string ErrorMessage
    {
        get { throw new NotImplementedException(); }
    }
}
 
public class EngineTest
{
    private IRazorEngine m_Engine;
 
    public EngineTest()
    {
        m_Engine = new CustomEngine();
    }
}


Or did I miss something?

xiety
October 24, 2012

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

> Unfortunately generic parameters don't inherit

Can you use covariance here?
interface IRazorEngine<out TBaseTemplateType>

Rick Strahl
October 24, 2012

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

@Caco - yes that would work for 'just making it work'. But to make this 'clean' semantically I'd have to add much more of the interface (various options to render and compile add assemblies and namespaces etc.). The actual 'real world' interface to this class is much more complex. Additionally other methods include parameters that reflect the generic type...

If I just go in and create a simple interface as you suggest to make it work then I'm just hacking the code to make it work, which IMHO is no better than using dynamic - and adds a heck of a lot more noise.

I can relate though - I usually spend a bit of time thinking about static typing first before going down the path of dynamic typing. Great discussion though - just goes to show you can usually make static typing work but the gymnastics required to do so often are a pain and that's really where dynamic shines. It can make something complex quite a lot simpler.

@Brian - CoVariance, hmmm... I didn't even know that syntax existed for generic types. I have to take a look, but that looks promising.

Interesting that all the comments here appear to favor of NOT using dynamic and instead using more complex workarounds even for a one of operation... :-) I thought that this would be a perfect use case where dynamic makes sense to avoid excessive extra code and dependencies.

Caco
October 25, 2012

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

Well, normally I have to suppress the urge to use new stuff like dynamic (if you can still call it new ;)), but I happened to read a post the other day which had some interesting points about the downside of dynamic: http://lanzkron.wordpress.com/2012/10/22/use-of-dynamic-causes-trust-issues-between-developer-and-compiler-according-to-anonymous-blogger/

Richard
November 02, 2012

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

> the Engine is of type RazorEngine<'ThisClass'> which I'm not sure how it could be expressed as a generic expression

If you were free to change the base class, it is possible to have a generic type parameter which references the current class:

public class RazorEngine<TBaseTemplateType> 
  where TBaseTemplateType : RazorTemplateBase<TBaseTemplateType>, new()
{
   public RazorTemplateBase<TBaseTemplateType> CreateTemplate()
   {
      return new TBaseTemplateType
      {
         Engine = this
      };
   }
}
 
public abstract class RazorTemplateBase<TBaseTemplateType> 
  where TBaseTemplateType : RazorTemplateBase<TBaseTemplateType>, new()
{
   public RazorEngine<TBaseTemplateType> Engine { get; set; }
}
 
public class MyTemplate : RazorTemplateBase<MyTemplate>
{
}


As you say, this would require some mental gymnastics. :)

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024