使用反射的对象实例化适用于 VB.NET 但不适用于 C#

Object instantiation using Reflection works in VB.NET but not C#

我正在尝试从 dll 中实例化一个对象而不引用它。我可以在 VB.NET 中使用反射来做到这一点,但无法弄清楚如何在 C# 中做到这一点。

在VB.NET中:

Public Class Form1

Dim bytes() As Byte = System.IO.File.ReadAllBytes("\path\directory\file.dll")
Dim assmb As System.Reflection.Assembly = System.Reflection.Assembly.Load(bytes)
Dim myDllClass As Object = assmb.CreateInstance("myNamespace.myClass")

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    Dim conStr As String = myDllClass.publicConString
    Dim dt As DataTable = myDllClass.MethodReturnsDatatable("select * from Part", conStr)
    DataGridView1.DataSource = dt

End Sub

在 C# 中:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    static byte[] bytes = System.IO.File.ReadAllBytes(@"\path\directory\file.dll");
    static System.Reflection.Assembly assmb = System.Reflection.Assembly.Load(bytes);
    object myDllClass = assmb.CreateInstance("myNamespace.myClass");

    private void Form1_Load(object sender, EventArgs e)
    {
        string conStr = myDllClass.publicConString;
        DataTable dt = myDllClass.MethodReturnsDatatable("select * from Part", conStr);
        dataGridView1.DataSource = dt;
    }                
}

我收到这两个错误:

Error 1 'object' does not contain a definition for 'publicConString' and no extension method 'publicConString' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?) C:\Users\Username\Desktop\C#\FormTest\FormTest\Form1.cs 29 34 FormTest

Error 2 'object' does not contain a definition for 'MethodReturnsDatatable' and no extension method 'MethodReturnsDatatable' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?) C:\Users\Username\Desktop\C#\FormTest\FormTest\Form1.cs 30 33 FormTest

VB.NET 将允许您执行 "Late Binding"(当未使用 option strict 或通过项目属性明确允许时。)这将使运行时检查对象是否在调用它之前有一个特定的方法。这在 C# 中也是可能的,但是您需要明确地告诉运行时您想要允许这样做。您可以通过将对象标记为 dynamic.

 dynamic myDllClass = assmb.CreateInstance("myNamespace.myClass");

Dynamic 将解决您的直接问题,但需要付出一定的代价:

  • 调用动态方法比调用非动态方法慢得多。
  • 此外,您的代码可以正常编译,但可能会在运行时失败。
  • 并且 Intellisense 将无法帮助您建议正确的方法名称(和大小写,因为 C# 区分大小写)。

但更好的解决方案是,如果您知道 class 的类型(在本例中,将其转换为该类型(或转换为由 [=53= 实现的接口) ] 或者你的 class 延伸的基础 class:

 myClass myDllClass = (myClass) assmb.CreateInstance("myNamespace.myClass");

这将需要您添加对包含 myClass class.

的项目的程序集引用

您可以通过创建包含基础 class 或接口的共享程序集来改进您的模型:

在共享程序集中:

 public interface myInterface
 {
     string publicConString { get; };
     DataTable MethodReturnsDatatable(string sql, string connectionString);
 }

在您的 file.dll 中,添加对包含 myInterface:

的 assembly/project 的引用
 public class myClass : myInterface{}

在您使用 myClass 的项目中,还添加对包含 myInterface:

的 assembly/project 的引用
 myInterface myDllClass = (myInterface) assmb.CreateInstance("myNamespace.myClass");

这样你就不需要直接引用 file.dll,允许你在运行时加载不同的实现,但它确实确保你只调用正确的方法并且你的代码知道如何处理。