我想在运行时加载并实例化位于App_Code文件夹中的类。
这些类实现了IModule
:
public interface IModule
{
String Test();
}
测试类:
// ~/App_Code/Test.cs
namespace ModuleManagementSystem
{
class Test : IModule
{
public String Test()
{
return "Testing! One, two, thee!";
}
}
}
类文件由系统用户上传,并充当模块。
模块的类名将始终与模块文件名相同。
我正在寻找功能正常的代码。
我会尽快给你赏金。
namespace ModuleManagementSystem
{
public sealed class Compile
{
public void ToDLL(String sourcefile, String outputfile)
{
var compilerResults =
CodeDomProvider.CreateProvider("CSharp").CompileAssemblyFromFile(
new CompilerParameters {
OutputAssembly = outputfile,
GenerateInMemory = false,
TreatWarningsAsErrors = false,
GenerateExecutable = false,
},
sourcefile
);
}
}
}
上述工作正常:
// ~/App_Code/Test.cs
public class Test
{
// ...
}
但是如果我实现我的IModule
界面:
namespace ModuleManagementSystem
{
public interface IModule
{
String HelloWorld();
}
}
我收到以下错误:
{C:\的Inetpub \ wwwroot的\ ModuleManagementSystemWeb \ App_Code文件\ test.cs中(4,21) :错误CS0246:类型或命名空间 名称'ModuleManagementSystem'可以 找不到(你错过了使用 指令或程序集 参考?)} System.CodeDom.Compiler.CompilerError
IModule
接口和Compile
类都位于同一个类库中,该类是从Web应用程序引用的:
答案 0 :(得分:2)
实际上传到App_Code文件夹是一个坏主意。我会使用一个ASP.NET不知道的单独文件夹。这样你就不会让框架试图为你自动编译代码。
您可以使用CSharpCodeProvider
轻松编译和运行代码 - 有关示例,请参阅my source code for Snippy。
我希望这仅用于内部(和经过身份验证)的使用 - 我不建议让不受信任的用户在您的Web服务器上执行他们的代码。你可以通过运行非常低权限的代码使所有稍微更安全,但你仍然冒着代码紧密循环的风险等。
编辑:在回答您更新的问题时,您只需要提供适当的程序集以供参考,其中包含IModule
。请参阅CompilerParameters.ReferencedAssembles
属性。
答案 1 :(得分:1)
Assembly assembly = Assembly.Load(assemblyName);
IModule instance = assembly.CreateInstance(typeName) as IModule;
您也可以使用Activatore.CreateInstance()
方法创建实例,而无需明确引用程序集。
答案 2 :(得分:0)
你可以使用反射来做到这一点,这是一个非常简单的方法,它会返回你传递给函数的模块名[class name]的实例
Public Shared Function GetDALInstance(ByVal moduleClassName As String) As IModule
Dim className As String
dim path as string = <<NamespacePath>>
className = Path + moduleClassName
Return Assembly.Load(Path).CreateInstance(className)
End Function
上面的方法是在vb.net中你可以简单地将其转换为c#
答案 3 :(得分:0)
我决定在运行时加载的类必须实现给定的接口,并且类的名称必须与文件名相同。
将类上传到并编译为的文件夹无关紧要。
加载已编译的类(.dll)并将其实例化:
return (IInterfaceClassesMustImplement)Assembly
/* continued --> */ .LoadFile("c:\...\SomeClass.dll")
/* continued --> */ .CreateInstance("SomeClass");
编译课程:
internal static class Compiler
{
internal static void AssemblyFromFile(
String classFilePath,
String assemblyFilePath,
String[] referencedAssemblies
)
{
var cp = new CompilerParameters { OutputAssembly = assemblyFilePath };
foreach (String ra in referencedAssemblies)
{
cp.ReferencedAssemblies.Add(ra);
}
CompilerResults cr = CodeDomProvider.CreateProvider("CSharp")
/* continued --> */ .CompileAssemblyFromFile(cp, classFilePath);
if (cr.Errors.Count > 0) // throw new Exception();
}
}