我使用CSharpCodeProvider来构建动态C#,它运行良好。比表达式树快一点,当然更容易维护表达式树和IL ...
我遇到的情况似乎不会起作用。
ConsoleApp1.exe MyClass的
然后我使用CSharpCodeProvider生成内存临时DLL。比方说,像这样基本的东西:
void TestFunc(MyClass输入) { }
这会生成编译器错误,因为CSharpCodeProvider没有对MyClass的引用。由于MyClass位于EXE中,因此添加对编译器对象的引用不起作用。我收到错误消息,说它无法找到ConsoleApp1的元数据。
有没有在EXE的上下文中使代码生效?或者有什么方法可以使参考工作?我知道如果我将MyClass移动到DLL然后将其作为参考添加它,这是有效的,但这对我的班级用户来说是一个不可接受的要求。
编辑:
因此,使用纯表达式树,我生成了这个方法:
.Lambda #Lambda1<System.Func`2[ConsoleApplication2.Source,ConsoleApplication2.Dest]>(ConsoleApplication2.Source $var1) {
.New ConsoleApplication2.Dest(){
S1 = .Call $var1.get_S1(),
S2 = .Call $var1.get_S2(),
I1 = .Call $var1.get_I1(),
I2 = .Call $var1.get_I2(),
S3 = .Call $var1.get_S3(),
S4 = .Call $var1.get_S4(),
S5 = .Call $var1.get_S5()
}
}
编译为lambda,调用1M次需要~285ms。
“编译”方式,我生成这段代码:
namespace ConsoleApplication2
{
public class TestClass
{
public static ConsoleApplication2.Dest TestFunc(ConsoleApplication2.Source source)
{
ConsoleApplication2.Dest d = new ConsoleApplication2.Dest();
d.S1 = source.S1;
d.S2 = source.S2;
d.I1 = source.I1;
d.I2 = source.I2;
d.S3 = source.S3;
d.S4 = source.S4;
d.S5 = source.S5;
return d;
}
}
}
然后我构建了一个类型化的lambda:
ParameterExpression p1 = Expression.Parameter(typeof(Source));
var v = Expression.Lambda<Func<Source, Dest>>(Expression.Call(mi, p1), new ParameterExpression[] { p1 }).Compile();
当我调用v(obj)1M次时,纯表达式树的时间只需要133ms 1/2。
由于要求类必须在EXE中公开,甚至在DLL中,我只是对这条路线犹豫不决。
知道为什么表达式树这么慢了吗?
答案 0 :(得分:0)
有没有在EXE的上下文中使代码生效?
没有。 CSharpCodeProvider
在运行时创建一个程序集,因此无法注入&#34;注入&#34;进入当前运行的程序集,这是一个在那时编译的程序集。
有什么方法可以使参考工作吗?
您自己回答了这个问题 - 将EXE扩展名添加到引用名称中,以便它知道加载EXE而不是DLL。