使用Reflection的对象实例化在VB.NET中工作但不在C#中工作

bry*_*k3y 2 .net c# vb.net dll system.reflection

我试图从dll实例化一个对象而不引用它.我可以使用VB.NET中的Reflection来实现它,但无法弄清楚如何在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
Run Code Online (Sandbox Code Playgroud)

在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;
    }                
}
Run Code Online (Sandbox Code Playgroud)

我收到这两个错误:

错误1"对象"不包含"publicConString"的定义,并且没有扩展方法"publicConString"接受类型为"object"的第一个参数(您是否缺少using指令或程序集引用?)C:\ Users\Username\Desktop\C#\ FormTest\FormTest\Form1.cs 29 34 FormTest

错误2"对象"不包含"MethodReturnsDatatable"的定义,并且没有可以找到接受"object"类型的第一个参数的扩展方法"MethodReturnsDatatable"(您是否缺少using指令或程序集引用?)C:\ Users\Username\Desktop\C#\ FormTest\FormTest\Form1.cs 30 33 FormTest

jes*_*ing 5

VB.NET将允许您执行"后期绑定"(当option strict未使用时或者通过项目属性明确允许时).这将使运行时在调用之前检查对象是否具有某种方法.这在C#中也是可能的,但是你需要明确告诉运行时你想要允许它.您可以通过将对象标记为动态来完成此操作.

 dynamic myDllClass = assmb.CreateInstance("myNamespace.myClass");
Run Code Online (Sandbox Code Playgroud)

动态将解决您的直接问题,但它需要付出代价:

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

但是更好的解决方案是,如果您知道类的类型(在这种情况下,您将其转换为该类型)(或者由类实现的接口或类扩展的基类):

 myClass myDllClass = (myClass) assmb.CreateInstance("myNamespace.myClass");
Run Code Online (Sandbox Code Playgroud)

这将要求您向包含myClass该类的项目添加程序集引用.

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

在共享程序集中:

 public interface myInterface
 {
     string publicConString { get; };
     DataTable MethodReturnsDatatable(string sql, string connectionString);
 }
Run Code Online (Sandbox Code Playgroud)

在您的file.dll添加对程序集/项目的引用,包含myInterface:

 public class myClass : myInterface{}
Run Code Online (Sandbox Code Playgroud)

在您的项目中,myClass还要添加对程序集/项目的引用,其中包含myInterface:

 myInterface myDllClass = (myInterface) assmb.CreateInstance("myNamespace.myClass");
Run Code Online (Sandbox Code Playgroud)

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