实现简单的CSharpShell -- OrcShell (2) 类型浏览、执行代码片断与其它

简介:
  二、类型管理

1、程序集与类型的管理

Context初始化时便将AppDomain中的类型全部加载并交给TypeManager管理:


         public  Context()
        
{
            ……
            TypeManager 
= new TypeManager();
            Assemblys 
= new Dictionary<String, Assembly>();
            Assembly[] al 
= AppDomain.CurrentDomain.GetAssemblies();
            
foreach (Assembly a in al)
            
{
                AddAssembly(a);
            }


            AppDomain.CurrentDomain.AssemblyLoad 
+= new AssemblyLoadEventHandler(CurrentDomain_AssemblyLoad);
……
        }



private   void  AddAssembly(Assembly a)
        
{
            
if (a != null)
            
{
                Assemblys.Add(a.FullName, a);
                Type[] tl 
= a.GetTypes();

                
foreach (Type t in tl)
                
{
                    
if(!t.FullName.StartsWith("<PrivateImplementationDetails>"))
                        TypeManager.AddType(t);
                }

            }

        }


        
void  CurrentDomain_AssemblyLoad( object  sender, AssemblyLoadEventArgs args)
        
{
            Assembly a 
= args.LoadedAssembly;
            
if (!Assemblys.ContainsKey(a.FullName))
            
{
                AddAssembly(a);
            }

        }


开发时发现,程序集中有一批类型名字以"<PrivateImplementationDetails>"开头的类型,貌似时临时类型,这些东西数量较多,干脆把它屏蔽掉了。

2、进出命名空间

CdClassCmdHandler 中实现,目前不支持级联操作,即:cdc ..cdc .; cdc namespaceName这样是可以的,cdc ../ns1/ns2 这样是不支持的。输入的命名空间名称可以只是部分,程序自动进行匹配,如只有1个匹配项则自动进入该项,否则不进行操作,同时打印所有匹配项。

3列出命名空间和类型

 ListClassCmdHandler 中实现,支持正则表达式匹配。幕后工作由TypeDictionary在做:


            Context.TypeManager.Now.ListDir(match);
            Context.TypeManager.Now.ListType(match);

         public   void  ListType(String match)
        
{
            Regex re 
= null;

            
if (match != null)
            
{
                re 
= new Regex(match);
            }


            
foreach (Type t in Types.Values)
            
{
                String name 
= t.Name;
                
if (re != null)
                
{
                    
if (!re.IsMatch(name)) continue;
                }

                Console.WriteLine(
"C:\t" + Context.EnsureAtLeastLength(name,20+ "\t" + t.FullName);
            }

        }


        
public   void  ListDir(String match)
        
{
            Regex re 
= null;

            
if (match != null)
            
{
                re 
= new Regex(match);
            }


            
foreach (TypeDictionary dic in SubTypeDictionary.Values)
            
{
                String name 
= dic.Name;
                
if (re != null)
                
{
                    
if (!re.IsMatch(name)) continue;
                }

                Console.WriteLine(
"N:\t" + Context.EnsureAtLeastLength(name, 20+ "\t" + dic.FullName);
            }

        }


4、查看类型

扩展方法确实是好东西,有了它这里实现起来很简单。在 ClassExtensionMethods 实现:

     public   static   class  ClassExtensionMethods
{
    ……
        
public static void methods(this Type t)
        
{
            
foreach (MethodInfo mi in t.GetMethods())
            
{
                Console.WriteLine(
"  " + mi);
            }

        }


        
public static void methods(this Object obj)
        
{
            
if (obj == nullreturn;

            methods(obj.GetType());
        }


        
public static void props(this Type t)
        
{
            
foreach (PropertyInfo pi in t.GetProperties())
            
{
                Console.WriteLine(
"  " + pi);
            }

        }


        
public static void props(this Object obj)
        
{
            
if (obj == nullreturn;

            props(obj.GetType());
        }


        
public static void members(this Type t)
        
{
            
foreach (MemberInfo mi in t.GetMembers())
            
{
                Console.WriteLine(
"  " + mi);
            }

        }


        
public static void members(this Object obj)
        
{
            
if (obj == nullreturn;

            members(obj.GetType());
        }


        
public static void creaters(this Type t)
        
{
            
foreach (ConstructorInfo ci in t.GetConstructors())
            
{
                Console.WriteLine(
"  " + ci);
            }

        }


        
public static void creaters(this Object obj)
        
{
            
if (obj == nullreturn;

            creaters(obj.GetType());
        }

    }



三、执行代码片断

 CscCmdHandler 实现。核心方法为 CscCmdHandler.Run(),代码如下:


        public   override   void  Run()
        
{
            
if (String.IsNullOrEmpty(InputCmdString)) return;
            String fullCmd 
= String.Empty;
            
if (Context.TypeManager.Now != Context.TypeManager.Root)
            
{
                fullCmd 
+= "                using " + Context.TypeManager.Now.FullName + ";";
            }

            
            fullCmd 
+=
@"                using System;
                using System.IO;
                using System.Text;
                using System.Collections.Generic;
                using Orc.Shell.Core;

                namespace Orc.Shell.Core.Dynamic 
                { 
                    public class DynamicClass
                    {
                        public Orc.Shell.Core.Context Context;

                        public void Save(String name, Object obj)
                        {
                            Context.Save(name,obj);
                        }

                        public Object My(String name)
                        {
                            return Context[name];
                        }

                        public void MethodInstance(Context context)
                        {
                            Context = context;
                            
" + InputCmdString + @";
                        }
                    }
                }
";

            CompilerResults cr 
= Context.CodeProvider.CompileAssemblyFromSource(Context.CompilerParameters, fullCmd);

            
if (Context.Debug)
            
{
                Console.WriteLine(
"Source:");
                Console.WriteLine(
"--------------------------------");
                Console.WriteLine(fullCmd);
                Console.WriteLine(
"--------------------------------");
                Console.WriteLine(
"Results");
            }


            
if (cr.Errors.HasErrors)
            
{
                Console.WriteLine(
"编译错误:");
                
foreach (CompilerError err in cr.Errors)
                
{
                    
if (Context.Debug)
                    
{
                        Console.WriteLine(String.Format(
"line {0}: {1}", err.Line, err.ErrorText));
                    }

                    
else
                    
{
                        Console.WriteLine(err.ErrorText);
                    }

                }

            }

            
else
            
{
                Assembly assem 
= cr.CompiledAssembly;
                Object dynamicObject 
= assem.CreateInstance("Orc.Shell.Core.Dynamic.DynamicClass");
                Type t 
= assem.GetType("Orc.Shell.Core.Dynamic.DynamicClass");
                MethodInfo minfo 
= t.GetMethod("MethodInstance");
                minfo.Invoke(dynamicObject, 
new Object[] { Context });
            }

        }

其中 CodeProviderCompilerParameters   Context 中初始化:

            CodeProvider  =   new  CSharpCodeProvider( new  Dictionary < string string > ()  "CompilerVersion""v3.5" } } );
            CompilerParameters 
=   new  CompilerParameters( new []  "mscorlib.dll""System.Core.dll""Orc.Shell.Core.dll""OrcShell.exe" } );
            CompilerParameters.GenerateExecutable 
=   false ;
            CompilerParameters.GenerateInMemory 
=   true ;

可以通过 Save(String name, Object obj)  My(String name) 来同环境进行交互。其中,Save(String name, Object obj) 是将代码片断中的对象 obj 保存为环境变量,变量名称为 nameMy(String name)取出名称为name 的环境变量,加载到代码段上。my 指令可以查看所有环境变量。

采用$name的方式操作环境变量更简介、直观,但这样一来代码难度加大不少,没想到什么简洁的实现,就没采用。

四、其它

1、扩展方法

对于常用的方法通过扩展方法来方便使用。如,打印一个对象 obj 到控制台上,正常写法是System.Console.WriteLine(obj.ToString()),比较麻烦,通过扩展方法,可以使它简化为:obj.p();相关代码如下:


     public   static   class  ClassExtensionMethods
    
{
        
public static void Print(this Object obj)
        
{
            Console.WriteLine(obj);
        }


        
public static void p(this Object obj)
        
{
            Print( obj );
        }


        
public static void P(this Object obj)
        
{
            Print(obj);
        }


        
public static void print(this Object obj)
        
{
            Print(obj);
        }

    ……
    }

2、变量缩写(Alias)

指令缩写可明显降低操作量。可通过编辑程序集目录下的 Alias.xml 文件来添加、删除或更改指令缩写。

Alias 指令可以查看目前的指令缩写。

五、缺乏的功能。

到现在为止,OrcShell只实现了Shell的雏型。由于只开发了一个晚上,测试也不是很完善,另外许多重要功能还未涉及,主要包括:

1、手动加载程序集;

2、常用系统管理功能,如常用的Shell 指令;

3、远程控制;

4、指令的自动完成。

留待后续。

本文转自xiaotie博客园博客,原文链接http://www.cnblogs.com/xiaotie/archive/2008/02/29/1085834.html如需转载请自行联系原作者


xiaotie 集异璧实验室(GEBLAB)

相关文章
【每日一题Day245】面试题 16.19. 水域大小 | dfs
【每日一题Day245】面试题 16.19. 水域大小 | dfs
179 0
|
缓存 负载均衡 Dubbo
Dubbo服务集群容错原理(重要)
该文章主要介绍了Dubbo服务集群容错的原理,包括集群容错技术的概念、Dubbo中使用的集群容错技术种类及其原理。
|
10天前
|
人工智能 自然语言处理 文字识别
阿里云百炼Qwen3.7-Max简介:能力、优势、支持订阅计划参考
Qwen3.7-Max是阿里云百炼面向智能体时代推出的新一代旗舰模型,对标GPT-5.5、Claude Opus 4.7等闭源旗舰。该模型支持百万级token上下文窗口,具备顶级推理能力、多模态搜索与视觉理解增强、流式输出低延迟响应等核心优势,覆盖编程、办公、长周期自主执行等复杂场景。同时支持OpenAI接口兼容,便于系统快速迁移。用户可通过Token Plan团队或节省计划等订阅方式灵活调用,适合企业级高要求场景使用。
4250 20
阿里云百炼Qwen3.7-Max简介:能力、优势、支持订阅计划参考
|
12天前
|
人工智能 自然语言处理 供应链
|
18天前
|
人工智能 开发工具 iOS开发
Claude Code 新手完全上手指南:安装、国产模型配置与常用命令全解
Claude Code 是一款运行在终端环境中的 AI 编程助手,能够直接在命令行中完成代码生成、项目分析、文件修改、命令执行、Git 管理等开发全流程工作。它最大的特点是**任务驱动、终端原生、轻量高效、多模型兼容**,无需图形界面、不依赖 IDE 插件,能够深度融入开发者日常工作流。
3665 15
|
14天前
|
人工智能 Linux BI
国内用 Claude Code 终于不用翻墙了:一行命令搞定,自动接 DeepSeek
JeecgBoot AI专题研究 一键脚本:Claude Code + JeecgBoot Skills + DeepSeek 全平台接入 一行命令装好 Claude Code + JeecgBoot Skills + DeepSeek 接入,无需翻墙使用 Claude Code,支持 Wind
3156 9
国内用 Claude Code 终于不用翻墙了:一行命令搞定,自动接 DeepSeek
|
5天前
|
存储 定位技术 数据库
CodeGraph 如何让 Claude Code减少 7 成工具调用?
CodeGraph 为 Coding Agent 提供本地代码知识图谱,把函数、类、调用链和框架路由提前整理成“项目地图”,减少盲目搜索和文件读取。它不是新 Agent,而是上下文基础设施,让 Agent 更快找到正确代码路径,平均减少 7 成工具调用。
707 0