如果您的用户拥有必要的工具(例如 Visual Studio,如果他们正在编写 C# 类,他们确实应该拥有),他们可以为您提供一个 DLL,然后您可以加载该 DLL动态:
private static T CreateInstance(string assemblyName, string typeName)
{
var assembly = Assembly.LoadFrom(assemblyName);
if (assembly == null)
throw new InvalidOperationException(
"The specified assembly '" + assemblyName + "' did not load.");
Type type = assembly.GetType(typeName);
if (type == null)
throw new InvalidOperationException(
"The specified type '" + typeName + "' was not found in assembly '" + assemblyName + "'");
return (T)Activator.CreateInstance(type);
}
T 泛型参数在那里,因此您可以传递 abstract class 或 interface 将类型实例强制转换为:
public interface IDoSomething
{
bool DoSomething();
}
您的用户在编写自己的类时从该接口继承:
public class UserDefinedClass : IDoSomething
{
public bool DoSomething()
{
// Implementation here.
}
}
这允许您保持类型安全并直接调用类方法,而不是依赖反射来这样做。
如果你真的希望你的用户提供 C# 源,你可以compile their class at runtime 这样:
private Assembly BuildAssembly(string code)
{
var provider = new CSharpCodeProvider();
var compiler = provider.CreateCompiler();
var compilerparams = new CompilerParameters();
compilerparams.GenerateExecutable = false;
compilerparams.GenerateInMemory = true;
var results = compiler.CompileAssemblyFromSource(compilerparams, code);
if (results.Errors.HasErrors)
{
var errors = new StringBuilder("Compiler Errors :\r\n");
foreach (CompilerError error in results.Errors )
{
errors.AppendFormat("Line {0},{1}\t: {2}\n",
error.Line, error.Column, error.ErrorText);
}
throw new Exception(errors.ToString());
}
else
{
return results.CompiledAssembly;
}
}
然后,您只需在上面的CreateInstance 代码中替换生成的程序集,而不是外部加载的程序集。请注意,您的用户仍需要在其类的顶部提供适当的 using 语句。
互联网上也有一些地方解释了 C# 中的how to get an Eval() function,以防你真的不需要完整的课程。