实现简单的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
212 0
|
缓存 负载均衡 Dubbo
Dubbo服务集群容错原理(重要)
该文章主要介绍了Dubbo服务集群容错的原理,包括集群容错技术的概念、Dubbo中使用的集群容错技术种类及其原理。
|
7天前
|
存储 弹性计算 缓存
阿里云服务器租赁费用:新版租赁收费标准及活动报价参考
本文更新了2026年阿里云全系列云服务器租赁活动报价,所有特惠资源均可前往阿里云活动中心选购,整体覆盖从个人入门到企业级高性能场景的全梯度需求。其中轻量应用服务器主打极致性价比,2核2G峰值200M带宽配置每日10点、15点限时抢购价仅38元/年,2核4G配置379元/年起;高性价比的经济型e实例、通用算力型u2i实例覆盖2核4G至4核32G全档位,适配开发测试与中小型企业业务;搭载英特尔至强6处理器的第九代c9i企业级实例算力较上代提升20%,支撑高并发生产环境,不同实例规格价差清晰,用户可根据自身业务负载与预算灵活选型。
1753 117
|
8天前
|
人工智能 程序员 API
Codex 接入 DeepSeek-V4-Flash:还能补上识图,提供两套方案
Codex 接入 DeepSeek-V4-Flash 怎么配?本文覆盖 CLI 与桌面端,再用 qwen3-vl-flash 补识图,两套方案可直接照做
1253 9
|
14天前
|
云安全 人工智能 运维
阿里云联动百位企业安全专家,共识Agent防御最佳实践
当Agent成为新员工,你的安全边界在哪里?
1956 9
阿里云联动百位企业安全专家,共识Agent防御最佳实践
|
8天前
|
编解码 人工智能 安全
2核4G/4核8G/8核16G阿里云服务器如何选择实例?经济型e、通用算力型u2i与计算型c9i选哪个?
本文介绍了阿里云2核4G、4核8G、8核16G三档主流配置下经济型e、通用算力型u2i和计算型c9i三种实例的最新活动价格与适用场景。同配置下三者价差显著,以2核4G为例,经济型e低至599.93元/年,计算型c9i则高达1742.08元/年。文章详细解析了各实例的性能定位:经济型e适合轻负载入门场景,u2i兼顾稳定算力与性价比,c9i凭借第9代至强处理器与芯片级安全能力支撑高性能业务。同时提示用户可叠加满减优惠券享受折上折,建议根据业务负载与预算综合决策。
543 112
缓存 安全 IDE
967 2
|
20天前
|
人工智能 前端开发 Linux
Codex 桌面版安装 + CC Switch 接入第三方 API 完整教程(2026 最新)
2026最新教程:手把手教你安装Codex桌面版,通过CC Switch v3.17.0一键接入Fenno等国产API(兼容OpenAI Responses格式),跳过账号登录,完整启用代码审查、多步任务与上下文感知功能。零基础友好,全程图文实操。(239字)
2943 4