tempad
Readygo技术搜索引擎 >>ASP技术 >> 如何动态引用DLL???

如何动态引用DLL???

Readygo技术搜索引擎 网络搜索 efish 2008-1-14 6:26:09

如何动态引用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

责任编辑: efish 参与评论 查找更多:
相关文章
各位大虾有个问题请教了 各位大虾有个问题请教了
急呀,请教大侠,一个数据库的问题 急呀,请教大侠,一个数据库的问题
标准菜鸟级问题 标准菜鸟级问题
哪里有Poser4软件的免费下载? 哪里有Poser4软件的免费下载?
求助高手!关于发布的问题 求助高手!关于发布的问题
如何查看2000中的帐号是何时建立的? 如何查看2000中的帐号是何时建立的?
获取IP地址的API是什么? 获取IP地址的API是什么?
怎样把表单的内容用WORD形式保存?? 怎样把表单的内容用WORD形式保存??
Free BCC5.5如何使用(哪有参考和实例),我会用MASM … Free BCC5.5如何使用(哪有参考和实例),我会用MASM 对BCC5.5下的.INC和.LIB文件很陌生,不知如何用。
本人用VB编写了一个小程序,编译后,运行正常,但是… 本人用VB编写了一个小程序,编译后,运行正常,但是我每点击程序一次,它就打开一次,有没办法让它打开后,再点击时就不再新打开一个了!
2秒记住本站域名

玩过泡泡龙吗?Readygo?Go! 再加上.Com.Cn的后缀,那就是大名小顶的readygo.com.cn

分类导航
Readygo技术搜索引擎