【问题标题】:Dynamically loading Assembly动态加载程序集
【发布时间】:2016-11-22 13:47:29
【问题描述】:

过去,我编写了一个应用程序,它可以根据数据库中的值动态加载 DLL 及其所有依赖项,如下所示(清理了一些参数)

VB

Dim oType As System.Type
Dim oAssembly As System.Reflection.Assembly
Dim oObject As System.Object
oAssembly = Assembly.LoadFrom(path)
oType = oAssembly.GetType("LogicValidator")
oObject = Activator.CreateInstance(oType)

oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir)
Console.WriteLine("Begin processing...")
oObject.ProcessBatch(cm_uid)

现在,当我在 C# 中编写类似的东西时,在构建应用程序之前出现错误,说明如下:

C#

System.Type oType = default(System.Type);
System.Reflection.Assembly oAssembly = default(System.Reflection.Assembly);
System.Object oObject = null;
oAssembly = Assembly.LoadFrom(path);
oType = oAssembly.GetType("LogicValidator");
oObject = Activator.CreateInstance(oType);
oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir);
Console.WriteLine("Begin processing...");
oObject.ProcessBatch(cm_uid);

错误

“object”不包含“Initialise”的定义,并且找不到接受“object”类型的第一个参数的扩展方法“Initialise”(您是否缺少 using 指令或程序集引用?)1234565 >

如果某个方法在运行时加载,我的 C# 应用程序如何在编译之前识别该方法不存在?

编辑

为了帮助其他偶然发现这个问题的人,我删除了以下内容。虽然它确实指出了答案,但其他人回答得更有说服力。 :-)

我想补充一点,以下内容有效 - 但前提是加载的程序集依赖项已经存在。

var DLL = Assembly.LoadFile(path);
Type type = DLL.GetType("LogicValidator");
dynamic c = Activator.CreateInstance(type);
c.Initialise("param1", "param2", "param3", audit, UserInfo, workingDir);
Console.WriteLine("Begin processing...");
c.ProcessBatch(cm_uid);

【问题讨论】:

  • 不要使用System.Object作为oObject的类型,使用你需要的实际类型(即LogicValidator)。否则dynamic 可能是你最好的选择。

标签: c# vb.net


【解决方案1】:

如果您在编译时不知道类型,您可以通过将类型声明为 dynamic 来使用动态运行时:

var oAssembly = Assembly.LoadFrom(path);
var oType = oAssembly.GetType("LogicValidator");
dynamic oObject = Activator.CreateInstance(oType);
oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir);
Console.WriteLine("Begin processing...");
oObject.ProcessBatch(cm_uid);

但是,您可能会考虑一种方法,其中加载的类型实现已知接口(将在插件和代码都引用的程序集中声明该接口):

public interface IProcessor
{
    void Initialise(
        string param1, 
        string param2, 
        string param2, 
        AuditTail auditTrail, 
        UserInfo userInfo, 
        DirectoryInfo workingDir);

    void ProcessBatch(int uid);
}

然后您可以按如下方式创建实例并获得完整的 IntelliSense 支持和类型检查:

var oAssembly = Assembly.LoadFrom(path);
var oType = oAssembly.GetType("LogicValidator");
IProcessor oObject = Activator.CreateInstance(oType);
oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir);
Console.WriteLine("Begin processing...");
oObject.ProcessBatch(cm_uid);  

【讨论】:

    【解决方案2】:

    您需要将oObject 数据类型更改为dynamic,如下所示:

    System.Type oType = default(System.Type);
    System.Reflection.Assembly oAssembly = default(System.Reflection.Assembly);
    dynamic oObject = null;
    oAssembly = Assembly.LoadFrom(path);
    oType = oAssembly.GetType("LogicValidator");
    oObject = Activator.CreateInstance(oType);
    oObject.Initialise("param1", "param2", "param3", AuditTrail, UserInfo, workingDir);
    Console.WriteLine("Begin processing...");
    oObject.ProcessBatch(cm_uid);
    

    更多关于dynamic:dynamic (C# Reference)

    【讨论】:

    • 谢谢你的回答,你打败了我!我已经更新了我的问题。
    【解决方案3】:

    您不需要像其他答案所说的那样将其转换为动态,您还可以继续使用不会调用 DLR 并且在这种情况下应该更快的反射,特别是因为您已经加载了必要的反射对象:

    var oAssembly = Assembly.LoadFrom(path);
    var oType = oAssembly.GetType("LogicValidator");
    var oObject = Activator.CreateInstance(oType);
    var oInitialiseMethod = oType.GetMethod("Initialise"); //See note below the code.
    var oProcessBatchMethod = oType.GetMethod("ProcessBatch"); //See note below the code.
    oInitialiseMethod.Invoke(oObject, "param1", "param2", "param3", AuditTrail, UserInfo, workingDir);
    Console.WriteLine("Begin processing...");
    oObject.ProcessBatch(cm_uid);
    

    您需要使用 Type.GetMethod 的重载,它接受 Type[] 作为函数参数,以便签名匹配。我已经为你做了,但我不知道其中一些是什么类型。

    见https://msdn.microsoft.com/en-us/library/system.type.getmethod(v=vs.110).aspx

    不过,正如另一个答案所说,接口在这里也是一个很好的解决方案 - 取决于应用程序的整体结构以及是否适合您的场景。

    【讨论】:

      猜你喜欢
      • 2016-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多