实现简单的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)

相关文章
|
4月前
|
Java 数据库连接 应用服务中间件
表单数据返回不到,HTTP状态 404 - 未找未找到,解决方法,针对这个问题,写一篇文章,理一下思路,仔细与原项目比对,犯错的原因是Mapper层的select查询表单数据写错,注意打开的路径对不对
表单数据返回不到,HTTP状态 404 - 未找未找到,解决方法,针对这个问题,写一篇文章,理一下思路,仔细与原项目比对,犯错的原因是Mapper层的select查询表单数据写错,注意打开的路径对不对
|
6月前
|
存储
VSTO 撤回代码修改的值
这段代码实现了一个简单的撤销功能。它使用一个栈(`Stack&lt;Action&gt;`)来存储操作,`SetCellValues`方法记录单元格的当前状态(值)并在栈中保存恢复操作。`UndoLastOperation`方法检查栈是否为空,如果不为空,则弹出顶部的操作并执行以撤销最近的更改。
|
6月前
如何解决由引起的IQKeyboardManager部分页面返回的键盘高度比实际小或最后收到键盘隐藏通知却显示了键盘问题
如何解决由引起的IQKeyboardManager部分页面返回的键盘高度比实际小或最后收到键盘隐藏通知却显示了键盘问题
91 0
|
6月前
|
开发者
在用户关闭页面时,提示用户有内容未保存-论onbeforeunload事件的用法
在用户关闭页面时,提示用户有内容未保存-论onbeforeunload事件的用法
93 0
element close事件关闭表单,数据替换掉原始列表的数据bug解决
element close事件关闭表单,数据替换掉原始列表的数据bug解决
74 0
|
JSON 小程序 数据格式
零基础学小程序008----小程序列表实现+本地json数据解析渲染到小程序列表
零基础学小程序008----小程序列表实现+本地json数据解析渲染到小程序列表
108 0
|
前端开发 测试技术
clswindow使用案例:防止vb程序重复打开,如果重复打开则激活当前已经打开的程序
clswindow使用案例:防止vb程序重复打开,如果重复打开则激活当前已经打开的程序
275 0
clswindow使用案例:防止vb程序重复打开,如果重复打开则激活当前已经打开的程序
|
Web App开发 Windows
当UI走查说页面色值错误时,先别急着检查代码
颜色一直是UI设计师们非常敏感的问题,为何屏幕会出现色差?工作中如何避免?
on方法多次绑定会多次执行的解决方法
on方法多次绑定会多次执行的解决方法
125 0
|
小程序 JavaScript DataX
小程序 — 实现左滑删除效果②
前言:这章我们为movable-view添加点击事件,完善左滑效果。 GitHub:https://github.com/Ewall1106/miniProgramDemo 1、 拖动事件 (1)在上一章中,我们给movable-view绑定了一个...
1238 0