Xiangism

从一个无知角落里开始,蹒跚学步,一个未知到另一个未知,在跌跌撞撞中越走越快,越走越远,最后宇宙也为之开源。对于探索者来说,最后他们的思想总是变得和自己的足迹一样伟大。
随笔 - 62, 文章 - 1, 评论 - 220, 阅读 - 20万
  博客园  :: 首页  :: 联系 :: 管理
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

C#实现任意大数的计算和简单逻辑命题的证明——前言

Posted on   Xiangism  阅读(2096)  评论(5编辑  收藏  举报

介绍

这是本人毕业设计的项目,一直想将其整理成文,可一不小心4年就过去了(这个时间又可以读个大学了)。现在给自己定一个目标,一个月时间里将项目的所有关键点都整理出来。不然真怕一眨眼又一个4年过去了,而代码依然躺在硬盘里。

项目取名MathAssist,使用vs2008。分成四个子项目:

  1. MathAssistLibrary    提供一个接口,以便实现用dll拓展的插件机制
  2. SuperCalculator   实现任意大数计算的插件
  3. 命令证明              实现简单逻辑命题证明的插件
  4. MathAssist          主程序,会扫描并加载其路径下所有符合条件的dll

其主程序可以从插件中扫描可用的命令,也可以显示插件中可用的窗体。如下是主程序界面,其加载了两个插件:“superCalculator”和“命令证明”。它们分别提供命令cal prove。

点击菜单项"插件"的子菜单后可以分别打开两个插件中实现的窗口。如下图

分别实现了大数计算和逻辑命题的证明。

在这篇前言中就先只介绍插件机制的实现吧,大数计算和逻辑命题的证明就留给后面的系列。

插件机制的实现

MathAssistLibrary接口的定义

在MathAssistLibrary项目中只定义了两个接口: ICommand, IForm,分别用于提供命令行功能和窗口功能。

复制代码
 1     /// <summary>命令接口</summary>
 2     public interface ICommand
 3     {
 4         /// <summary>命令名称</summary>
 5         string Name { get; }
 6 
 7         /// <summary>执行命令</summary>
 8         /// <param name="cmd">命令参数</param>
 9         /// <returns>返回的结果</returns>
10         string Excute( string cmd );
11 
12         /// <summary>对命令的使用作相应的说明</summary>
13         string Describe { get; }
14     }
15     /// <summary>获得插件的窗体</summary>
16     public interface IForm
17     {
18         /// <summary>窗体名</summary>
19         string Text { get; }
20 
21         /// <summary>窗体对象</summary>
22         Form GetForm { get; }
23     }
MathAssistLibrary
复制代码

ICommand接口

  • Name 用于表示命令的名称
  • Excute 用于执行命令
  • Describe 用于对这个命令提供一个简要的帮助文档说明

IForm接口

  • Text 用于表示窗体的名称
  • GetForm 用于获取Form对象。在主程序中获取Form对象后,再调用Show()即可显示之。

插件实现

在插件项目中只要实现ICommand和IForm两个接口即可,以SuperCalculator为例:

复制代码
public partial class frmSuperCalculator : Form, IForm
{
        string IForm.Text {
            get { return "计算器"; }
        }

        frmSuperCalculator frm;
        Form IForm.GetForm {
            get {
                if (frm == null || frm.IsDisposed) {
                    frm = new frmSuperCalculator();
                }
                return frm;
            }
        }
        ...  
}
复制代码
复制代码
public class Calculator : MathAssistLibrary.ICommand
{
        string MathAssistLibrary.ICommand.Describe {
            get { return "cal命令可以进行相关的数学运算。比如cal 1+max(2,3)*2"; }
        }
        string MathAssistLibrary.ICommand.Name {
            get { return "cal"; }
        }
        string MathAssistLibrary.ICommand.Excute(string cmd) {
            try {
                Expression exp = new Expression();
                exp.Format = cmd;
                return exp.Calculator().ToString();
            } catch (ExpressionException e) {
                return string.Format("表达式出错。出错类型:{0},出错位置{1}", e.Message, e.Index);
            }
        }
}
复制代码

 

主程序对插件的扫描

FindDllFile()函数找到与程序同路径下的所有dll文件,代码如下:

复制代码
 1         List<string> FindDllFile(string foldername) {
 2             DirectoryInfo dir = new DirectoryInfo(foldername);
 3             FileInfo[] files = dir.GetFiles();
 4             List<string> result = new List<string>();
 5 
 6             foreach (FileInfo fi in files) {
 7                 if (fi.Name.ToUpper().EndsWith(".DLL"))
 8                     result.Add(fi.FullName);
 9             }
10             return result;
11         }
FindDllFile
复制代码

LoadOne()从一个文件中找一个特定的类型,并返回其对象,代码如下:

复制代码
        private List<object> LoadOne(string filename, Type type) {
            List<object> result = new List<object>();

            try {
                Assembly ass = Assembly.LoadFrom(filename);
                Module[] mods = ass.GetModules();

                foreach (Module mod in mods) {
                    Type[] typs = mod.GetTypes();

                    foreach (Type typ in typs) {
                        if (type.IsAssignableFrom(typ)) {
                            result.Add(ass.CreateInstance(typ.FullName));
                        }
                    }
                }
            } catch (BadImageFormatException) {

            }
            return result;
        } // end func
复制代码

 先用Assembly.LoadFrom()加载程序集,然后获取所有模块,最后在所有模块中用type.IsAssignableFrom()找与传入参数type相匹配的类型,如果匹配那么就创建一个对象并返回。

在主程序中分别用如下两行代码调用LoadOne() 

List<object> cmd = LoadOne(filename, typeof(ICommand));
List<object> frm = LoadOne(filename, typeof(IForm));

 这样用cmd.Excute()就可以执行插件中实现的代码,用frm.Show()就可以显示插件中所实现的窗体。

 

现提供MathAssist.exe的下载路径。在后面的文章中会给出整个程序的源码,敬请期待~~

 

 参数文献:  http://www.cnblogs.com/conexpress/archive/2009/03/04/MyCalculator_01.html

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示
目录导航