I have found some questions here on SO that have shown several methods to instantiate a class from a string, the only one i found how to make work was Activator.CreateInstance
. Knowing it wasn't the fastest i tried to find something else and found Compiled Expressions
.
Now, how could i implement a Compiled Expression
to instantiate a new class based on a given string as its type ? Is it possible ?
This is my code:
public List<HtmlBlock> ParseBlocks( Page page, ControllerContext controller )
{
var nodeBlocks = GetNodes( page.html );
var blocks = new List<HtmlBlock>();
Parallel.ForEach( nodeBlocks, block => blocks.Add( ParseNode( block, controller ) ) );
return blocks;
}
private static HtmlBlock ParseNode( HtmlBlock block, ControllerContext controller )
{
try
{
//Instantiate the class
var type = Activator.CreateInstance( null, "Site.ViewModels." + block.Type );
//Populate selected template
block.SetHtml( new HelperController().RenderView( block.Template, type.Unwrap(), controller ) );
return block;
}
//Suppress any error since we just want to hide the block on parse error
catch (Exception)
{
block.SetHtml( "" );
return block;
}
}
Just to give some context, i'm trying to create a custom template builder, the user can input an HTML tag like this one:
<template dir="_Courses" where="active=1" order="name" type="CoursesViewModel"></template>
And i will render the selected template with data from my DB. What i need is to instantiate the CoursesViewModel
with 4 parameters: string where, string select, string order, int take
, those are my query filtering parameters.
OBS: I have also tried to work with FastActivator but to use it i have to also use `Type.GetType( "Site.ViewModels." + block.Type ) and i thik that it would end up as costly as my other option, it this right ?
EDIT 1
I have executed two tests using my MVC application and applied 3 different methods, the results are in miliseconds and where used 20k iterations. The third one is a method that uses a switch/case to look for the correct class by
1) ViewModelFactory.CreateInstance("NameSpace.ClassName", "", "", "", 0)
2) Activator.CreateInstance(null, "NameSpace.ClassName")
3) HtmlParser.GetClassType("ClassName")
------------------------------------------------------------------------
1st Test 2nd Test | 20k
1) 93068 | 110499
2) 117460 | 89995
3) 82866 | 77477
I used a PasteBin to share the code. Oddly the methods have worked differently on each case, on the first execution @Ivan Stoev was the slowest code but on the page refresh his code worked better and my switch/case was the fastest. Could anyone please explain why this ?
EDIT 2
These tests implemented the changed version of Ivan Stoev's code where the Dictionary was changed to ConcurrentDictionary and the Activator was implemented with parameters
1) ViewModelFactory.CreateInstance( "ClassName", "", "", "", 0 )
2) var type = Type.GetType( "NameSpace.ClassName" );
var obj = Activator.CreateInstance( type, new object[] { "", "", "", 0 } );
3) HtmlParser.GetClassType("ClassName")
------------------------------------------------------------------------
1st Test 2nd Test | 200k
1) 3418 | 3674
2) 5759 | 5859
3) 3776 | 4117
Here is the bin with the modified code: PasteBin