【发布时间】:2016-03-14 18:39:34
【问题描述】:
我在这里发现了一些关于 SO 的问题,这些问题展示了几种从字符串实例化类的方法,我发现的唯一一种方法是 Activator.CreateInstance。知道这不是最快的,我试图找到其他东西并找到Compiled Expressions。
现在,我如何实现Compiled Expression 来实例化一个基于给定字符串作为其类型的新类?有可能吗?
这是我的代码:
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;
}
}
只是为了提供一些上下文,我正在尝试创建一个自定义模板构建器,用户可以输入这样的 HTML 标记:
<template dir="_Courses" where="active=1" order="name" type="CoursesViewModel"></template>
我将使用我的数据库中的数据呈现选定的模板。我需要用 4 个参数实例化 CoursesViewModel:string where, string select, string order, int take,这些是我的查询过滤参数。
OBS:我也尝试过使用FastActivator,但要使用它,我还必须使用 `Type.GetType("Site.ViewModels." + block.Type) 并且我认为它最终会像我的其他选择一样昂贵,对吗?
编辑 1
我已经使用我的 MVC 应用程序执行了两个测试并应用了 3 种不同的方法,结果以毫秒为单位,并且使用了 20k 次迭代。第三个是使用switch/case来寻找正确的类的方法
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
我使用PasteBin 来分享代码。奇怪的是,这些方法在每种情况下的工作方式都不同,第一次执行时@Ivan Stoev 是最慢的代码,但在页面刷新时,他的代码工作得更好,而我的 switch/case 是最快的。谁能解释一下这是为什么?
编辑 2
这些测试实现了 Ivan Stoev 代码的更改版本,其中 Dictionary 更改为 ConcurrentDictionary 并且 Activator 是通过参数实现的
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
这里是修改后代码的 bin:PasteBin
【问题讨论】:
-
我不知道它是否会变得更快。无论如何,您都需要使用某种形式的反射。除非...您有固定数量的类并且直接实例化。
-
@JeffMercado,直接实例化是什么意思?我不能使用
Compiled Expressions? -
就像做这样的事情:
if (block.Type == "SomeType") return new SomeType(); -
所以你想通过名称来实例化类,它有 4 个参数
string where, string select, string order, int take的构造函数,对吗?还是只是无参数构造函数? -
嗯,你需要测量。但是这个选项是存在的。但我不确定我之前的评论中你想要什么类型的构造函数:(A) 还是 (B)?