反射和注册事件

最近用到的反射比较多。在此总结和记录。

一、反射获取DLL信息

        /// <summary>
        /// 获取Dll的名称
        /// </summary>
        /// <param name="dllpath"></param>
        /// <returns></returns>
        public bool GetDLLName(string dllPath, out string dllName, out string dllGuid)
        {
            dllName = null;
            dllGuid = null;

            //可以注册使用了,其实此处的注册就是在树上加一个节点,然后把这个新的树反序列化到文件中
            //增加一个节点,此处必须知道这个工具叫什么名字了,还是需要看看这个东西
            Assembly assembly = Assembly.LoadFile(dllPath);

            //this.DebugLog("正在加载插件。。。");

            // 获取当前dll中的所有的public类型
            Type[] types = assembly.GetExportedTypes();
            Type typeUserControl = typeof(UserControl);
            int countUserControl = 0;
            Type typePlugin = null;
            foreach (Type type in types)
            {
                //验证当前的类型UserControl的类
                if (typeUserControl.IsAssignableFrom(type) && type.IsClass)
                {
                    typePlugin = type;
                    countUserControl++;
                }
            }
            if (countUserControl > 1)
            {
                //DevMessageBoxUtil.Info("被注册的dll插件中的公共类型多余1个\n请修改插件,使其公共类型个数为1。");
                throw new PluginCreatingException(ConstInfo.EXCEPTION_MSG_OVER_MUCH_PLUGIN);
                //return false;
            }
            else if (countUserControl < 1)
            {
                //DevMessageBoxUtil.Info("没有发现可被注册的插件");
                //return false;
                throw new PluginCreatingException(ConstInfo.EXCEPTION_MSG_PLUGIN_NOT_FOUND);
            }
            object plugin = Activator.CreateInstance(typePlugin);
            UserControl uc = plugin as UserControl;
            if (uc == null)
            {
                //DevMessageBoxUtil.Info("此插件不继承UserControl类");
                //return false;
                throw new PluginCreatingException(ConstInfo.EXCEPTION_MSG_PLUGIN_NOT_USERCONTROL);
            }
            // 向当前树节点添加一个子节点
            GeneralToolModel genTool = new GeneralToolModel();
            IEnumerator<CustomAttributeData> enumerator = assembly.CustomAttributes.GetEnumerator();
            enumerator.Reset();
            CustomAttributeData attrName = null;
            CustomAttributeData attrGuid = null;
            while (enumerator.MoveNext())
            {
                CustomAttributeData attrCurrent = enumerator.Current;
                if (attrCurrent.AttributeType == typeof(AssemblyTitleAttribute))
                {
                    attrName = attrCurrent;
                }
                if (attrCurrent.AttributeType == typeof(GuidAttribute))
                {
                    attrGuid = attrCurrent;
                }
            }
            if (attrName == null || attrGuid == null)
            {
                //DevMessageBoxUtil.Info("插件描述信息AssemblyInfo内容缺失,请修改插件");
                //return false;
                throw new PluginCreatingException(ConstInfo.EXCEPTION_MSG_PLUGIN_ASSEMBLY_INFO_NOT_DEFINED);
            }
            dllName = attrName.ConstructorArguments[0].Value.ToString();
            dllGuid = attrGuid.ConstructorArguments[0].Value.ToString();
            return true;

        } 

 

二、使用程序域获取DLL的概要信息,不会占用DLL,可以在不使用DLL的情况下热删除

1.RemoteLoader类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace XXX
{
    /// <summary>
    /// 目的:远程加载程序集,获取程序集中的可序列号信息或者执行方法
    /// 主程序域和子程序域直接无法传递不可序列化的对象,确认一下UC是否是可序列化的
    /// 创建人:王杰
    /// 创建日期:2018-08-24
    /// 修改描述:程序域和Dev的SplashScreenManager进度条冲突:程序域处理时间过长,静态的SplashScreenManager成为null,猜想可能被垃圾回收器回收了
    /// 处理结果:GetDLLName方法放置在了PluginService中
    /// 修改人:王杰
    /// 修改日期:2018-10-20
    /// 备注:
    /// </summary>
    public class RemoteLoader : MarshalByRefObject
    {
        #region uc无法穿越AppDomain边界,所以dll被使用后,必须重启
        //public UserControl GetUC(string dllpath)
        //{
        //    Assembly assembly = Assembly.LoadFile(dllpath);
        //    //this.DebugLog("正在加载插件。。。");

        //    // 获取当前dll中的所有的public类型
        //    Type[] types = assembly.GetExportedTypes();
        //    Type typeUserControl = typeof(UserControl);
        //    int countUserControl = 0;
        //    Type typePlugin = null;
        //    foreach (Type type in types)
        //    {
        //        //验证当前的类型UserControl的类
        //        if (typeUserControl.IsAssignableFrom(type) && type.IsClass)
        //        {
        //            typePlugin = type;
        //            countUserControl++;
        //        }
        //    }
        //    if (countUserControl > 1)
        //    {
        //        DevMessageBoxUtil.Info("被注册的dll插件中的公共类型多余1个\n请修改插件,使其公共类型个数为1。");
        //        return null;
        //    }
        //    else if (countUserControl < 1)
        //    {
        //        DevMessageBoxUtil.Info("没有发现可被注册的插件");
        //        return null;
        //    }
        //    object plugin = Activator.CreateInstance(typePlugin);
        //    UserControl uc = plugin as UserControl;
        //    if (uc == null)
        //    {
        //        DevMessageBoxUtil.Info("此插件不继承UserControl类");
        //        return null;
        //    }
        //    return uc;
        //}
        #endregion

        /// <summary>
        /// 获取Dll的名称
        /// </summary>
        /// <param name="dllpath"></param>
        /// <returns></returns>
        public bool GetDLLName(string dllPath, out string dllName, out string dllGuid)
        {
            //...同上
GetDLLName
        }
    }
}

2.使用RemoteLoader类

             string callingDomainName = AppDomain.CurrentDomain.FriendlyName;//Thread.GetDomain().FriendlyName; 

            //this.DebugLog(callingDomainName);
            AppDomain ad = AppDomain.CreateDomain("RemoteLoadePlugin");
            //Assembly ass = Assembly.GetExecutingAssembly();
            string currentAssembly = Assembly.GetExecutingAssembly().Location;
            RemoteLoader loader = (RemoteLoader)ad.CreateInstanceFromAndUnwrap(currentAssembly,
                typeof(RemoteLoader).ToString());

 

三、使用反射订阅事件

1.订阅

         /// <summary>

        /// 通过反射给订阅者注册事件
        /// </summary>
        /// <param name="publisher">发布者对象</param>
        /// <param name="subscriber">订阅者对象</param>
        /// <param name="EventName">订阅事件名称</param>
        /// <param name="CallbackName">事件的回调函数,此处必须为订阅者的实例函数</param>
        private void RegisterEvent(object publisher, object subscriber, string EventName, string CallbackName)
        {
            Type t = publisher.GetType();
            EventInfo eventInfo = t.GetEvent(EventName);
            if (eventInfo != null)
            {
                Type eventHanderType = eventInfo.EventHandlerType;
                Type tThis = subscriber.GetType();
                BindingFlags myBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
                MethodInfo methodCallback = tThis.GetMethod(CallbackName, myBindingFlags);

                //回调函数有静态函数和实例函数的区别,如果不设置第二个参数或为null,则表示为静态函数,就会出现this为null的情况
                Delegate del = Delegate.CreateDelegate(eventHanderType, subscriber, methodCallback);
                eventInfo.AddEventHandler(publisher, del);
            }
        }

2.使用

        void UCProfessionalTool_Load(object sender, EventArgs e)
        {
            this._service.DisplayProfessionalTool(this.tabMain, this._professionalTool, this._plugins);

            //注册每个插件的完成事件
             foreach (string key in this._plugins.Keys)
        {
        UserControl uc = this._plugins[key];
                //Type t = uc.GetType();
                //EventInfo eventInfo = t.GetEvent(PluginInfo.PLUGIN_EVENT_WORK_FINISHED);
                //if (eventInfo != null)
                //{
                //    Type eventHanderType = eventInfo.EventHandlerType;
                //    Type tThis = this.GetType();
                //    BindingFlags myBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
                //    MethodInfo methodCallback = tThis.GetMethod(PluginInfo.PLUGIN_CALLBACK_WORK_FINISHED, myBindingFlags);
                    
                //    //回调函数有静态函数和实例函数的区别,如果不设置第二个参数或为null,则表示为静态函数,就会出现this为null的情况
                //    Delegate del = Delegate.CreateDelegate(eventHanderType, this, methodCallback);
                //    eventInfo.AddEventHandler(uc, del);
                //}
                this.RegisterEvent(uc, this, PluginInfo.PLUGIN_EVENT_WORK_FINISHED, PluginInfo.PLUGIN_CALLBACK_WORK_FINISHED);
                this.RegisterEvent(uc, this, PluginInfo.PLUGIN_EVENT_WORK_FLOW_FINISHED, PluginInfo.PLUGIN_CALLBACK_WORK_FLOW_FINISHED);
        }


 

        } 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值