如何使用反射将动态方法绑定到DLL中声明的事件 [英] How to bind a method dynamically using reflection to the Event declared in dll

查看:150
本文介绍了如何使用反射将动态方法绑定到DLL中声明的事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


假设我创建了一个具有静态类并具有诸如
之类的静态事件的dll. DLL项目:

Hi,
Suppose I have created a dll that have an static class and have an static event like
DLL project:

public static class TestApplication
    {


          public static event TestStateHandler AfterTestComplete;
          public static void Startup();

    }



使用DLL的主项目.
现在我想绑定主项目Program.cs文件的方法.我可以调用Startup()方法,但是如何将program.cs方法绑定到AfterTestComplete event.
我正在使用此方法



Main Project that use DLL.
Now I want to bind a method of my main project Program.cs file.I am able to call Startup() method,but how to bind program.cs method to AfterTestComplete event.
I am using this approch

Assembly DLL = Assembly.LoadFile(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Refdll", "Tests.dll"));
                 //Get Test
                Type Test = DLL.GetType("Test");
               
                //Type dd=DLL.GetType("Fiddler.SessionStateHandler");

                MethodInfo IsStarted = Test.GetMethod("Startup");
                EventInfo AfterTestComplete;
                if (!Convert.ToBoolean(IsStarted.Invoke(null, null)))
                {

                    AfterTestComplete = Test.GetEvent("AfterSessionComplete");
                    Type delegateType = AfterTestComplete.EventHandlerType;
                    MethodInfo mm = AfterTestComplete.AddMethod;



现在如何将program.cs方法绑定到AfterTestComplete事件.



Now how to bind a method of program.cs to AfterTestComplete event.

推荐答案

我不知道为什么要使用程序集(程序集,而不是在运行时加载了"DLL"),但是您可能有自己的原因.
从一开始,您所做的工作就很糟糕.使用反射来查看您的代码.它依赖于硬编码的魔术词字符串"Test","Startup","AfterSessionComplete"等. 这是不支持的,而且非常不可靠.如果您拼错了这些魔术字中的任何一个,编译器将不会警告您,如果您决定更改某些名称,该怎么办?所以,这是垃圾,属于垃圾箱.

没有硬编码的反射问题可以简单地解决.例如,您可以创建一些主机应用程序程序集和插件程序集都已知的接口.可以在某些库程序集中声明它,但是您甚至可以在宿主应用程序程序集中声明它.插件程序集可以静态引用主机应用程序程序集(是的,尽管存在常见的误解,"EXE"程序集也可以被引用;在.NET中,"EXE"和"DLL"之间的区别不是必需的).它不会创建任何循环依赖项.

您始终可以在界面中使用一些事件声明.仅TestStateHandler类型不是很好.定义事件实例类型的主流方法是:首先定义从System.EventArgs派生的事件参数类型,然后在泛型System.EventHandler:
中使用它
I don''t know why you want to use the assembly (assembly, not "DLL") loaded during runtime, but you may have your reasons.

You are doing it in a bad way from the very beginning. Look at your code using reflection. It relies on hard-coded magic words the strings "Test", "Startup", "AfterSessionComplete", and the like. This is unsupportable and extremely unreliable. The compiler won''t warn you if you misspell any of these magic words, and what if you decide to change some of the names? So, this is rubbish which belongs to a dumpster.

The reflection problem without hard-coding can be simply resolved. For example, you could create some interface known to both host application assembly and the plug-in assembly. It could be declared in some library assembly, but you can even declare it in your host application assembly. The plug-in assembly can statically reference the host application assembly (yes, despite of one of the common misconception "EXE" assembly can also be referenced; in .NET, distinction between "EXE" and "DLL" is not essential). It would not create any circular dependencies.

You can always use some event declaration in your interface. Only TestStateHandler type is not so good. The mainstream way of defining event instance type is this: first define event arguments type derived from System.EventArgs and then use it in generic System.EventHandler:
public class MyEventArgs : System.EventArgs {/* ... */}

public interface IMyPlugin {
   public static event System.EventHandler<MyEventArgs> AfterTestComplete;
   // ...
}

但是,原则上,如果您确实需要,可以使用TestStateHandler,但是我不明白为什么...

怎么办?在主机应用程序中,您需要找到某种实现此接口的类型.如何?这是最简单的方法: https://msdn. microsoft.com/en-us/library/system.type.isassignablefrom%28v=vs.110%29.aspx [访问驻留的自定义对象在dll插件中 [通过程序集的字符串表示形式收集程序集类型 [ ^ ],
在现有实例上的C#反射InvokeMember [动态加载用户控件 [

But, in principle, you can use your TestStateHandler, if you really want it, but I don''t see why…

Now what? In the host application, you need to find some type which implements this interface. How? This is the simplest way: https://msdn.microsoft.com/en-us/library/system.type.isassignablefrom%28v=vs.110%29.aspx[^].

If more than one type implements this interface, do… whatever you want, say, use the first one, or deny the whole assembly as wrong one. I go further and define a special assembly-level attribute which claims that certain type(s) implement certain plug-in interface(s), and then I don''t have to traverse all the type, but have to check up this claim during runtime. You can find further detail in my past answers:
Access a custom object that resides in plug in dll[^],
Gathering types from assemblies by it''s string representation[^],
C# Reflection InvokeMember on existing instance[^],
Dynamically Load User Controls[^].

At the end of your reflection work, you instantiate the desired class which, as you found, implements the interface you want. For instantiation, you either use Activator.CreateInstance(Type), or use MethodInfo.Invoke on a constructor. So, you can safely type-cast the type reference to the interface reference:

IMyPlugin plugin = (IMyPlugin)instantiatedType;


从这一点出发,您可以使用对象引用plugin将事件处理程序添加到相关事件实例的调用列表中,或者像对待任何实例的任何实例一样,对该对象执行任何其他操作静态已知类型.

—SA


From this point, you can use the object reference plugin to add your event handler to the invocation list of the event instance in question, or do whatever else you need to do with this object, as you would do with any instance of any statically known type.

—SA


这篇关于如何使用反射将动态方法绑定到DLL中声明的事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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