以原始方式动态加载托管C#DLL和调用方法,就好像它是同一项目的一部分一样 [英] Dynamically load managed C# DLL and call method the original way as if it was a part of the same project

查看:45
本文介绍了以原始方式动态加载托管C#DLL和调用方法,就好像它是同一项目的一部分一样的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我搜索了网站,发现了一些如何使用InvokeMember方法在动态加载的DLL中执行方法的文章。



但我的问题是:



有没有办法动态加载托管/ C#DLL文件,在DLL中实例化一个类的对象并以正常方式调用对象的方法? />




以下是我要找的一个例子:





在DLL文件中(即动态加载):

  public   string  DoGreeting(){ return   < span class =code-string> Hello World; } 





在应用程序或ASP.NET网站中:



< pre lang =c#>程序集asm = Assembly.LoadFrom(strAbsolutePathToDllFile);
... myObject = DoSomeMagicUsingTheAssemblyToConvertObjectToCorrectType(asm);


// 使用应用程序输出结果:
MessageBox.Show(myObject.DoGreeting());

//

// 使用ASP.NET输出结果:
Response.Write(myObject.DoGreeting());





DLL文件可以是应用程序和ASP.NET网站使用的库(仅包含核心功能 - 不是网络相关的。



在示例中我发现类名(实际上是程序集,类名,方法名和参数)也被使用,这也没关系我为我的DLL文件和项目(应用程序和/或ASP.NET网站)编写了源代码。

解决方案

使用Reflection,当然可以。当您不仅需要加载此类程序集(我称之为插件,通过它们最常见的用途)时,还会出现一个小问题,但也会卸载它们。由于不允许卸载程序集,因此只能解决问题,抛出一个可以卸载的单独的应用程序域,但这导致需要通过IPC工作。如果您不需要卸载任何东西(例如,通常情况下,您可以定义在某些配置文件中使用的插件并在所有运行时使用它们),整个过程非常简单,如果您做得对。



只是避免按名称查找任何内容,这是一种容易出错的方法,更好地定义和实现一些插件接口



我在过去的答案中解释了这一切的大部分内容:

一般来说插件的用途是什么 [ ^ ],

创建使用可重新加载插件的WPF应用程序...... [ ^ ],

AppDomain拒绝加载程序集 [ ^ ],

使用CodeDom生成代码 [ ^ ],

< a href =http://www.codeproject.com/Answers/168158/Create-WPF-Application-that-uses-Reloadable-Plugin.aspx#answer1>创建使用可重新加载插件的WPF应用程序...... [ ^ ],

动态加载用户控件 [ ^ ](这里简单解释一下,你可能想从这个答案开始),

现有实例上的C#Reflection InvokeMember [ ^ ](还有这一个),

项目和DLL':如何保持它们可管理? [< a href =http://www.codeproject.com/Answers/326639/Projects-and-DLLs-How-to-keep-them-managable#answer3target =_ b lanktitle =新窗口> ^ ],

通过它的字符串表示从集合中收集类型 [ ^ ]。



不要害怕:这不是很难;这只是我对这个话题有很多疑问。



-SA


现在,另一种选择:使用Microsoft托管可扩展性框架:

http://en.wikipedia.org/ wiki / Managed_Extensibility_Framework [ ^ ],

http://mef.codeplex.com/ [ ^ ]。



-SA


使用此作为类更改名称以适合

 命名空间 myNamespace 
{
内部 MyClass
{
MyClass( )
{
}
private 静态 字符串 DoGreeting()
{
return helloworld;
}
私有 静态 string DoGreeting2( string value
{
if value == null
{
value = ;
}
return value ;
}
}}





现在在你要使用的代码中使用它



  const  BindingFlags MyBinding =(BindingFlags)( -  20); 
程序集asm = Assembly.LoadFrom(Application.StartupPath + \\ myClass.dll);
object obj = asm.CreateInstance( myNamespace.myClass true ,MyBinding, null null null null );
string result =( string )obj.GetType()。GetMethod( DoGreeting,MyBinding).Invoke( null ,< span class =code-keyword> null
);
MessageBox.Show(result);





并且使用方法2只是在传递字符串时执行与第一次相同的操作值显示为



  const  BindingFlags MyBinding =(BindingFlags) (-20); 
程序集asm = Assembly.LoadFrom(Application.StartupPath + \\ myClass.dll);
object obj = asm.CreateInstance( myNamespace.myClass true ,MyBinding, null null null null );
string result =( string )obj.GetType()。GetMethod( DoGreeting2,MyBinding).Invoke( null ,< span class =code-keyword> new
object [] { Hello America});
MessageBox.Show(result);


I searched the site and found several articles of how to execute methods inside a dynamically loaded DLL using InvokeMember method.

But my question is:

Is there a way to dynamically load a managed/C# DLL file, instanciate an object of the a class within the DLL and call the object''s methods the normal way?


Here is an example of what I am looking for:


In DLL file (that is to be loaded dynamically):

public string DoGreeting() { return "Hello World"; }



In Application or ASP.NET Web Site:

Assembly asm = Assembly.LoadFrom(strAbsolutePathToDllFile);
... myObject = DoSomeMagicUsingTheAssemblyToConvertObjectToCorrectType(asm);


// Output the result using application:
MessageBox.Show(myObject.DoGreeting());

// or

// Output the result using ASP.NET:
Response.Write(myObject.DoGreeting());



The DLL file could be a library that is to be used by both applications and ASP.NET web sites (containing only core functions - not web related).

In the examples I found the class name (actually the assembly, class name, method name and arguments) is also used which is also okay since I wrote the source code for both my DLL file and project (application and/or ASP.NET web site).

解决方案

With Reflection, of course you can. A little problem appears when you need not only to load such assemblies (I call them plug-ins, by their most typical use), but also unload them. As unloading of assembly is not allowed, the problem is only solvable throw a separate Application Domain which you can unload, but it leads to the need to work through IPC. If you don''t need to unload anything (which is also often the case, say, you define what plug-in to use in some configuration file and use them all the run time), the whole thing is fairly simple, if you do it right.

Only avoid finding anything by name, this is an error-prone approach, better define and implement some plug-in interface.

I explain most of the aspects of it all in my past answers:
What is the use of plugin in general[^],
Create WPF Application that uses Reloadable Plugins...[^],
AppDomain refuses to load an assembly[^],
code generating using CodeDom[^],
Create WPF Application that uses Reloadable Plugins...[^],
Dynamically Load User Controls[^] (simple part explained here, you may want to start with this answer),
C# Reflection InvokeMember on existing instance[^] (and also this one),
Projects and DLL''s: How to keep them managable?[^],
Gathering types from assemblies by it''s string representation[^].

Don''t be afraid: it''s not really very hard; it''s just that I had many questions on the topic.

—SA


And now, one alternative: using Microsoft Managed Extensibility Framework:
http://en.wikipedia.org/wiki/Managed_Extensibility_Framework[^],
http://mef.codeplex.com/[^].

—SA


use this as the class change the name to fit

namespace myNamespace
{
internal class MyClass
{
MyClass()
{
}
private static string DoGreeting()
{
return "helloworld";
}
private static string DoGreeting2(string value)
{
if(value == null)
{
value = "";
}
return value;
}
}}



now to use this in code you would use

const BindingFlags MyBinding = (BindingFlags)(-20);
            Assembly asm = Assembly.LoadFrom(Application.StartupPath + "\\myClass.dll");
            object obj = asm.CreateInstance("myNamespace.myClass", true, MyBinding, null, null, null,null);
            string result = (string)obj.GetType().GetMethod("DoGreeting", MyBinding).Invoke(null, null);
            MessageBox.Show(result);



and to use method 2 just do the same as the first while passing the string value to display as such

const BindingFlags MyBinding = (BindingFlags)(-20);
            Assembly asm = Assembly.LoadFrom(Application.StartupPath + "\\myClass.dll");
            object obj = asm.CreateInstance("myNamespace.myClass", true, MyBinding, null, null, null,null);
            string result = (string)obj.GetType().GetMethod("DoGreeting2", MyBinding).Invoke(null, new object[]{"Hello America"});
            MessageBox.Show(result);


这篇关于以原始方式动态加载托管C#DLL和调用方法,就好像它是同一项目的一部分一样的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆