cad.net IExtensionApplication接口的妙用 分開寫"啟動運行"函數 20191227更新


cad提供的 IExtensionApplication 接口 是不能實現一次以上的,那么這給編寫代碼帶來了一種不好的情況是,每次都要去修改實現這個接口的類,

如果是一個小的測試功能,你又要去動前面的核心,這樣就感覺很蛋疼....編程思維上面叫做"開閉原則":對拓展進行開放,對修改進行關閉.

所以我是這么想的,在實現IExtensionApplication接口的 Initialize 和  Terminate 時候,

用反射來找到某個接口(仿IExtensionApplication接口的),然后搜下面接口的 Initialize 和  Terminate,然后運行這個它.

20191227增加了控制加載順序的函數

 

仿IExtensionApplication接口的接口.

    /// <summary>
    /// 控制加載順序
    /// </summary>
    public enum Sequence : byte
    {
        First,// 最先 
        Last, // 最后
    }

    public interface IAutoGo
    {
        // 控制加載順序
        Sequence SequenceId();

        // 關閉cad的時候會自動執行   
        void Terminate();

        //打開cad的時候會自動執行  
        void Initialize();
    }

 

繼承 IExtensionApplication 接口的函數,cad加載這個dll,就會運行它.

    class RunClass
    {
        Type _ty;
        public string NamePace { get; private set; }
        public string ClassName { get; private set; }
        public Sequence SequenceId
        {
            get
            {
                Sequence sequence = Sequence.Last;
                try
                {
                    string sequenceId = "SequenceId";
                    _ty = Assembly.Load(NamePace).GetType(ClassName); //加載命名空間下的class
                    MethodInfo method = _ty.GetMethod(sequenceId);    //獲取這個class的方法

                    //居然是靜態獲取返回的枚舉值
                    object instanceObject = Activator.CreateInstance(_ty);
                    object returnValue1 = method.Invoke(instanceObject, null); //運行 
                    sequence = (Sequence)returnValue1;
                }
                catch
                { }
                return sequence;
            }
        }

        public RunClass(string namePace, string className)
        {
            NamePace = namePace;
            ClassName = className;
        }

        public void Run(string methodInfoName)
        {
            try
            {
                MethodInfo method = _ty.GetMethod(methodInfoName);     //獲取這個class的方法
                if (method.IsStatic)//判斷是否靜態方法
                {
                    method.Invoke(null, null);//靜態調用
                }
                else //非靜態,調用實例化方法
                {
                    object instanceObject = Activator.CreateInstance(_ty);
                    object returnValue1 = method.Invoke(instanceObject, null); //運行
                }
            }
            catch (System.Exception)
            {
                throw;
            }
        }
    }

    //為了解決IExtensionApplication在一個dll內無法多次實現接口的關系
    //所以在這里反射加載所有的IAutoGo,以達到能分開寫"啟動運行"函數的目的
    public class AutoClass : IExtensionApplication
    {
        //打開cad的時候會自動執行     
        public void Initialize()
        {
            RunIAutoGo("Initialize");
        }

        //關閉cad的時候會自動執行
        public void Terminate()
        {
            //可以用
            //MessageBox.Show("哇哇哇哇哇");

            //不可以用,此時的cad界面都已經關閉了...涉及內存釋放的問題
            //Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

            RunIAutoGo("Terminate");
        }


        // 通過反射獲取所有繼承了IAutoGo接口的類!
        // https://www.cnblogs.com/yelanggu/p/5196156.html      
        // 然后反射實例化,運行它!
        // https://www.cnblogs.com/yanshanshuo/p/3905621.html

        void RunIAutoGo(string methodName = "Initialize")
        {
            const string iAutoGo = "IAutoGo";
            var typeList = new List<RunClass>(); //儲存
            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())//當前的應用程序域,也就是acad或者gcad的域
            {
                foreach (Type getTypes in assembly.GetTypes())//獲取類型集合
                {
                    foreach (Type getInterfaces in getTypes.GetInterfaces())//獲取接口集合
                    {
                        if (getInterfaces != null &&
                            !string.IsNullOrEmpty(getInterfaces.Name) &&
                            getInterfaces.Name == iAutoGo)//找到接口的函數
                        {
                            //再找里面的Initialize
                            foreach (MemberInfo member in getTypes.GetMembers())//獲得它的成員(函數 方法)的信息集合
                            {
                                if (member != null && !string.IsNullOrEmpty(member.Name))
                                {
                                    if (member.Name == methodName)
                                    {
                                        string namePace = Assembly.GetExecutingAssembly().ToString();  //命名空間
                                        string className = member.ReflectedType.FullName;              //類名    
                                        typeList.Add(new RunClass(namePace, className));
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //按照 SequenceId 排序
            typeList = typeList.OrderBy(runClass => runClass.SequenceId).ToList();

            var sb = new StringBuilder();
            int num = 0;
            foreach (var item in typeList)
            {
                try
                {
                    item.Run(methodName);
                }
                catch (System.Exception e)
                {
                    num++;
                    sb.Append("錯誤");
                    sb.Append(num.ToString());
                    sb.Append("\n\r");
                    sb.Append("探索接口RunIAutoGo出錯,錯誤NamePace:\n\r");
                    sb.Append(item.NamePace);
                    sb.Append("\n\r錯誤ClassName:\n\r");
                    sb.Append(item.ClassName);
                    sb.Append("\n\r錯誤信息:\n\r");
                    sb.Append(e.Message);
                    sb.Append("\n\r\n\r");
                } 
            }
            if (sb.Length > 0)
            {
                MessageBox.Show(sb.ToString(), "驚驚連盒");
            } 
        }
    }

 

 

 

封存上面的,之后也不用動了....

任何需要實現啟動運行的函數,都去實現  : IAutoGo

注意一下

    public class Test : IAutoGo
    {
        public Sequence SequenceId()
        {
            //最好只使用一次,用於初始化工具集的路徑之類的優先項
            return Sequence.First; 

            //其余均使用last
            //return Sequence.Last;
        }

        public void Initialize()
        {

            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;//命令欄交互 
            ed.WriteMessage("驚驚博客是 https://www.cnblogs.com/JJBox/ ");
        }

        public void Terminate()
        { }
    }

 

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM