使用反射的对象实例化适用于 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
,允许你在运行时加载不同的实现,但它确实确保你只调用正确的方法并且你的代码知道如何处理。
我正在尝试从 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
:
public class myClass : myInterface{}
在您使用 myClass
的项目中,还添加对包含 myInterface
:
myInterface myDllClass = (myInterface) assmb.CreateInstance("myNamespace.myClass");
这样你就不需要直接引用 file.dll
,允许你在运行时加载不同的实现,但它确实确保你只调用正确的方法并且你的代码知道如何处理。