简体   繁体   English

使用反射的对象实例化在VB.NET中有效,但在C#中不起作用

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

I'm trying to instantiate an object from a dll without referencing it. 我正在尝试实例化dll中的对象而不引用它。 I can do it using Reflection in VB.NET but can't figure out how to do it in C#. 我可以在VB.NET中使用Reflection来做到这一点,但无法弄清楚如何在C#中做到这一点。

In VB.NET: 在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

In C#: 在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;
    }                
}

I get these two errors: 我收到以下两个错误:

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 错误1'对象'不包含'publicConString'的定义,找不到扩展方法'publicConString'接受类型为'object'的第一个参数(您是否缺少using指令或程序集引用?)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 错误2'对象'不包含'MethodReturnsDatatable'的定义,找不到扩展方法'MethodReturnsDatatable'接受类型为'object'的第一个参数(您是否缺少using指令或程序集引用?)C:\\ Users \\ Username \\ Desktop \\ C#\\ FormTest \\ FormTest \\ Form1.cs 30 33 FormTest

VB.NET will allow you to do "Late Binding" (when option strict is not used or when it's explicitly allowed through the project properties.) which will let the runtime check whether the object has a certain method before callign it. VB.NET将允许您执行“后期绑定”(当未使用option strict时,或者在项目属性中明确允许使用它时)。这将使运行时在调用该对象之前检查该对象是否具有某种方法。 This is also possible in C#, but then you need to explicitly tell the runtime you want to allow this. 这在C#中也是可能的,但是随后您需要明确告诉运行时您要允许这样做。 You do it by marking the object as dynamic . 您可以通过将对象标记为dynamic来实现

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

Dynamic will solve your direct issue, but it comes at a cost: Dynamic将解决您的直接问题,但这需要付出一定的代价:

  • Invoking dynamic methods is is much slower than invoking a non-dynamic method. 调用动态方法比调用非动态方法要慢得多。
  • Plus, your code will compile just fine, but could fail at runtime. 另外,您的代码可以很好地编译,但是可能在运行时失败。
  • And Intellisense will not be able to help you suggest the correct method names (and casing, since C# is case sensitive). 而且Intellisense将无法帮助您建议正确的方法名称(以及大小写),因为C#区分大小写。

But a better solution would be, if you know the type of the class (which you do in this case, to cast it to that type (or to an Interface implemented by the class or a base class which your class extends from): 但是,如果您知道类的类型(在这种情况下,您可以将其强制转换为该类型)(或者转换为由该类实现的接口或您的类从其继承的基类实现),则更好的解决方案是:

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

This would require you to add an assembly reference to the project containing the myClass class. 这将需要您向包含myClass类的项目添加程序集引用。

You can improve your model by creating a shared assembly that contains the base class or interface: 您可以通过创建包含基类或接口的共享程序集来改进模型:

In the shared assembly: 在共享程序集中:

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

In your file.dll , add a reference to the assembly/project containing myInterface : 在您的file.dll ,添加对包含myInterface的程序集/项目的myInterface

 public class myClass : myInterface{}

In your project consuming myClass also add a reference to the assembly/project containing myInterface : 在消耗myClass的项目中,还添加对包含myInterface的程序集/项目的myInterface

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

This way you don't need to have a direct reference to file.dll , allowing you to load different implementations at runtime, but it does ensure that you're only calling proper methods and that your code knows how to deal with it. 这样,您无需直接引用file.dll ,从而允许您在运行时加载不同的实现,但可以确保仅调用正确的方法,并且代码知道如何处理它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM