Some of our controllers are currently redundant so I changed the base class' constructor to make sure no-one called them accidentally...
public abstract class MyRedundantBaseClass
{
public MyRedundantBaseClass()
{
throw new NotImplementedException();
}
}
Now, none of my tests go anywhere near this class (or any inherited ones) so why was it throwing the exceptions?
The problem is in one of the auto-generated classes in the T4MVC.cs file. The template generates a static field for each non-abstract controllers in your application...
public static class MVC
{
public static MyApp.Controllers.Account.AccountController Account = new MyApp.Controllers.Account.T4MVC_AccountController();
// Repeated for each controller...
}
This list of fields also included a number that extended my redundant class. So, as soon as I did anything with the T4MVC framework all these classes got automatically instantiated and now I'm dead in the water.
My solution is to edit the template so that it generates a Lazy Loading version of the T4MVC.cs file. This also makes it a little more efficient as it will only new-up classes when it needs them.
Here's the old template section (starting from line 73)...
<#foreach (var controller in DefaultArea.GetControllers()) { #>
public static <#=controller.FullClassName #> <#=controller.Name #> = new <#=controller.FullDerivedClassName #>();
<#} #>
... and here's what I changed it to...
<#foreach (var controller in DefaultArea.GetControllers()) { #>
private static <#=controller.FullClassName #> _<#=controller.Name #>;
<#} #>
<#foreach (var controller in DefaultArea.GetControllers()) { #>
public static <#=controller.FullClassName #> <#=controller.Name #>
{
get
{
if (_<#=controller.Name #> == null)
_<#=controller.Name #> = new <#=controller.FullDerivedClassName #>();
return _<#=controller.Name #>;
}
}
<#} #>
This now generates the following code in T4MVC.cs...
public static class MVC
{
private static MyApp.Controllers.Account.AccountController _Account;
public static MyApp.Controllers.Account.AccountController Account
{
get
{
if (_Account == null)
_Account = new MyApp.Controllers.Account.T4MVC_AccountController();
return _Account;
}
}
// Repeated for each controller...
}
I still need to add a double locking mechanism for thread safety, but I think this makes a valuable improvement to an already great framework.


Good idea, let's get this change in. Let's discuss by email offline. Thanks!
ReplyDelete