如何动态引用DLL???
如何动态引用DLL???
楼主()2002-05-14 15:04:38 在 .NET技术 / C# 提问 小弟想在应用程序中动态引用自己编写的DLL,但不通过在“项目”中“添加引用”来实现对DLL的引用,而是想通过直接在程序上编写代码来进行引用(这不是多余的,肯定有用)。
请高手指教指教,多谢了! 问题点数:50、回复次数:15Top
1 楼xiandaliu(仙达流,菜鸟先飞)回复于 2002-05-14 15:10:31 得分 0
Top
2 楼xiandaliu(仙达流,菜鸟先飞)回复于 2002-05-14 15:13:57 得分 0
例如:
using System.Runtime.InteropServices;
public static extern int MessageBox(int h, string m, string c, int type);
Top
3 楼gavinhe(gavinhe)回复于 2002-05-14 15:15:06 得分 0
请写得具体一点!Top
4 楼xiandaliu(仙达流,菜鸟先飞)回复于 2002-05-14 15:41:24 得分 5
即然我们需要引用外来库,所以必须导入一个Namespace:
using System.Runtime.InteropServices;
接着添加下面的代码来声明一个API:
public static extern int MessageBox(int h, string m, string c, int type);
此处DllImport属性被用来从不可控代码中调用一方法。”User32.dll”则设定了类库名。DllImport属性指定dll的位置,这个dll中包括调用的外部方法。Static修饰符则声明一个静态元素,而这个元素属于类型本身而不是上面指定的对象。extern则表示这个方法将在工程外部执行,使用DllImport导入的方法必须使用extern修饰符。
MessageBox 则是函数名,拥有4个参数,其返回值为数字。
大多数的API都能传递并返回值。
添中Click点击事件代码:
protected void button1_Click(object sender, System.EventArgs e)
{
MessageBox (0,"API Message Box","API Demo",0);
}
/*******************************************************************************
请访问http://www.yesky.com/20020307/1600638.shtmlTop
5 楼leebons(李)回复于 2002-05-14 15:44:17 得分 0
这些都不是动态的吧Top
6 楼gavinhe(gavinhe)回复于 2002-05-14 16:07:45 得分 0
这样可能解决对Windows API的调用比较好,但对于自己编写的DLL会不会太复杂了,能否想VB6.0那样Set objTest=CreateObject("test.dll"),就可以使用呢?Top
7 楼gavinhe(gavinhe)回复于 2002-05-14 16:45:23 得分 0
其实这里所谓的DLL是使用C#编写的类库,可能会令人误解。Top
8 楼jhnhu(玩的就是技术)回复于 2002-05-14 18:00:28 得分 0
>>动态引用自己编写的DLL<< 并且dll是用c#写的 ,right?
请查看System.Reflection类库,动态取得类库和启动的成员!
late bindingTop
9 楼gavinhe(gavinhe)回复于 2002-05-14 18:16:02 得分 0
to jhnhu:
可能使用C#编写的类库编译后为dll文件,所以由此提法,如果觉得不妥,小弟刚接触C#不久,请原谅。
能给出具体代码吗?Top
10 楼jhnhu(玩的就是技术)回复于 2002-05-14 18:21:50 得分 5
>>可能使用C#编写的类库编译后为dll文件<< ??
情况一 有些DLL会是c#写的,有些是一般的com;
情况二 没有用c#写的dll,都是com。
都不能用Reflection,Reflection只适合对.net的组件,进行 反射 。
看你怎么用了!Top
11 楼zgb2002(爱好者)回复于 2002-05-14 20:01:29 得分 0
我明白gavinhe兄的意识,比如你做的软件非常优秀,别人想做二次开发,比如AutoCAD、SolidWorks就可以动态加载DLL,而做软件时你不知道别人的DLL的文件名和入口,而你可以留一个接口,比如查找某个文件夹下的所有DLL文件,并全部加载而且加载软件菜单上,怎么做,请高手指教!!Top
12 楼zgb2002(爱好者)回复于 2002-05-14 20:12:38 得分 25
.NET 框架开发者指南
动态加载和使用类型 请参见
查看类型信息 | 动态加载和使用类型 | Type.InvokeMember | Assembly.Load | 转换概述
语言
C#
Visual Basic
全部显示
反射提供了由语言编译器(例如 Microsoft Visual Basic .NET 和 JScript)用来实现隐式晚期绑定的基础结构。绑定是查找与唯一指定的类型相对应的声明(即实现)的过程。由于此过程在运行时而不是在编译时发生,所以称作晚期绑定。Visual Basic .NET 允许您在代码中使用隐式的晚期绑定;Visual Basic 编译器将调用一个帮助器方法,该方法使用反射来获取对象类型。传递给帮助器方法的参数有助于在运行时调用正确的方法。这些参数包括对其调用方法的实例(对象)、被调用方法的名称(字符串)和传递给被调用方法的参数(对象数组)。
在以下代码示例中,Visual Basic 编译器使用反射隐式地对其类型在编译时未知的对象调用方法。HelloWorld 类具有一个 PrintHello 方法,它输出与传递给 PrintHello 方法的某些文本串联的“Hello World”。在该示例中调用的 PrintHello 方法实际上是 Type.InvokeMember;Visual Basic 代码允许按照对象 (helloObj) 的类型在编译时已知(早期绑定)而不是在运行时已知(晚期绑定)的方式来调用 PrintHello 方法。
Imports System
Module Hello
Sub Main()
" Set up variable.
Dim helloObj As Object
" Create the object.
helloObj = new HelloWorld()
" Invoke the print method as if it was early bound
" even though it"s really late bound.
helloObj.PrintHello("Visual Basic Late Bound")
End Sub
End Module
自定义绑定
除了由编译器隐式地用来进行晚期绑定之外,反射还可以在代码中显式地用来完成晚期绑定。
公共语言运行库支持多种编程语言,但这些语言的绑定规则各不相同。在早期绑定的情况下,代码生成器可以完全控制此绑定。但是,当通过反射进行晚期绑定时,必须用自定义绑定来控制绑定。Binder 类提供了对成员选择和调用的自定义控制。
利用自定义绑定,您可以在运行时加载程序集,获取有关该程序集中类型的信息,然后对该类型调用方法或访问该类型的字段或属性。如果您在编译时(例如当对象类型依赖于用户输入时)不知道对象的类型,就可以使用这种方法。以下代码示例显示在 HelloWorld.dll 程序集中使用反射动态调用的方法(首先在 Visual Basic .NET 中,然后在 C# 中)。
" This class is deployed as an assembly consisting of one DLL,
" called HelloWorld.dll.
Imports System
Public Class HelloWorld
" Constant Hello World string.
Private m_helloWorld As String = "Hello World"
" Default public constructor.
Public Sub New()
End Sub "New
" Print "Hello World" plus the passed text.
Public Sub PrintHello(txt As String)
" Output to the Console.
Console.WriteLine((m_helloWorld & " " & txt))
End Sub
End Class
Imports System
Imports System.Reflection
Module VisualBasicLateHello
Sub Main()
" Set up the variables.
Dim assem as System.Reflection.Assembly
Dim obj as Object
Dim helloType as Type
Dim printMethod as MethodInfo
" Load the assembly to use.
assem = System.Reflection.Assembly.Load("HelloWorld")
" Get the type to use from the assembly.
helloType = assem.GetType("HelloWorld")
" Get the method to use from the type.
printMethod = helloType.GetMethod("PrintHello")
" Create an instance of the type.
obj = Activator.CreateInstance(helloType)
" Create an array to hold the arguments.
Dim args(1) as Object
" Set the arguments.
args(0) = "From Visual Basic Late Bound"
" Invoke the method.
printMethod.Invoke(obj, args)
End Sub
End Module
C# 版本如下所示。
// This class is deployed as an assembly consisting of one DLL,
// called HelloWorld.dll.
using System;
public class HelloWorld {
// Constant Hello World string.
private const String m_helloWorld = "Hello World";
// Default public constructor.
public HelloWorld() {
}
// Print "Hello World" plus the passed text.
public void PrintHello(String txt) {
// Output to the Console.
Console.WriteLine(m_helloWorld + " " + txt);
}
}
// Illustrates reflection"s late binding functionality.
// Calls the PrintHello method on a dynamically loaded
// and created instance of the HelloWorld class.
using System;
using System.Reflection;
public class CSharpLateHello {
public static void Main() {
// Load the assembly to use.
Assembly assem = Assembly.Load("HelloWorld");
// Get the type to use from the assembly.
Type helloType = assem.GetType("HelloWorld");
// Get the method to call from the type.
MethodInfo printMethod = helloType.GetMethod("PrintHello");
// Create an instance of the HelloWorld class.
Object obj = Activator.CreateInstance(helloType);
// Create the args array.
Object;
// Set the arguments.
args = "From CSharp Late Bound";
// Invoke the PrintHello method.
printMethod.Invoke(obj, args);
}
}
InvokeMember 和 CreateInstance
使用 Type.InvokeMember 可调用类型的成员。各个类(如 System.Activator 和 System.Reflection.Assembly)的 CreateInstance 方法是特殊形式的 InvokeMember,它们可新建特定类型的实例。Binder 类用于在这些方法中进行重载决策和参数强制。
以下代码示例显示参数强制(类型强制)和成员选择三种可能的组合。在第 1 种情况中,不需要任何参数强制或成员选择。在第 2 种情况中,只需要成员选择。在第 3 种情况中,只需要参数强制。
public class CustomBinderDriver
{
public static void Main (string {};
t.InvokeMember ("PrintBob", flags, binder, null, args);
//Case 2. Only member selection is needed.
args = new Object {"5.5"};
t.InvokeMember ("PrintNumber", flags, binder, null, args);
}
public static void PrintBob ()
{
Console.WriteLine ("PrintBob");
}
public static void PrintValue (long value)
{
Console.WriteLine ("PrintValue ({0})", value);
}
public static void PrintValue (String value)
{
Console.WriteLine ("PrintValue\"{0}\")", value);
}
public static void PrintNumber (double value)
{
Console.WriteLine ("PrintNumber ({0})", value);
}
}
当多个成员具有相同的名称时,将需要重载决策。Binder.BindToMethod 和 Binder.BindToField 方法用于解析与单个成员的绑定。Binder.BindToMethod 还通过 get 和 set 属性访问器提供了属性解析。
BindToMethod 返回要调用的 MethodBase,如果无法进行这样的调用,则返回 null。虽然 MethodBase 返回值通常是 match 参数中所包含的值之一,但它并不必如此。
当存在 ByRef 参数时,调用方可能需要取回这些参数。因此,如果 BindToMethod 已经操作参数数组,Binder 会允许将参数数组映射回它的初始形式。为了实现这一目的,必须向调用方保证参数的顺序不会改变。当按名称传递参数时,联编程序将重新排列参数数组,这就是调用方所见的参数。
可用成员集包括在类型和任何基类型中定义的成员。如果指定 BindingFlags.NonPublic,将返回该成员集中具有任何可访问性的成员。如果未指定 BindingFlags.NonPublic,联编程序就必须强制可访问性规则。当指定 Public 或 NonPublic 绑定标志后,还必须指定 Instance 或 Static 绑定标志,否则不会返回任何成员。
如果只有一个成员具有给定名称,则不必进行回调,而在该方法上进行绑定。代码示例的第 1 种情况说明了这一点:只有一个 PrintBob 方法可用,因此不需要进行回调。
如果可用集中有多个成员,所有这些方法都将传递给 BindToMethod,它将选择正确的方法并将其返回。在代码示例的第 2 种情况下,有两个名为 PrintValue 的方法。对 BindToMethod 的调用将选择正确的方法。
ChangeType 执行参数强制(类型强制),以便将实参转换为选定方法的形参的类型。即使类型精确匹配,仍会为每个参数调用 ChangeType。
在代码示例的第 3 种情况下,类型为 String 值为“5.5”的实参传递给 Double 类型的形参的方法。要使调用成功,必须Top
13 楼qqchen79(知秋一叶)回复于 2002-05-14 23:58:58 得分 15
参考MSDN上关于一下几个方法的介绍:
//mydll.dll必须在当前目录下,或在GAC中
Assembly asm = AppDomain.CurrentDomain.Load("mydll");
Type tp = asm.GeType("MyType");
object o = Activator.CreateInstance(tp); //创建类实例
MethodInfo mi = tp.GetMethod(...); //取的方法描述
mi.Invoke(o, ...); //调用的对象,以及参数
如果要做应用程序扩展的话,可以定义一个Interface,
然后得到object之后把它cast到Interface上,就可以直接调用了。Top
14 楼gavinhe(gavinhe)回复于 2002-05-15 17:41:40 得分 0
多谢各位的指教,结帐!Top
15 楼zgb2002(爱好者)回复于 2002-07-20 21:56:57 得分 0
不一定非要在一个目录,如不在可用Assembly asm = AppDomain.CurrentDomain.LoadFile(dllpath+dllname);Top
-
相关文章
2秒记住本站域名
玩过泡泡龙吗?Readygo?Go! 再加上.Com.Cn的后缀,那就是大名小顶的readygo.com.cn
