zoukankan      html  css  js  c++  java
  • 实现简单的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<stringstring>() "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、指令的自动完成。

    留待后续。

    版权所有,欢迎转载
  • 相关阅读:
    PAT 解题报告 1009. Product of Polynomials (25)
    PAT 解题报告 1007. Maximum Subsequence Sum (25)
    PAT 解题报告 1003. Emergency (25)
    PAT 解题报告 1004. Counting Leaves (30)
    【转】DataSource高级应用
    tomcat下jndi配置
    java中DriverManager跟DataSource获取getConnection有什么不同?
    理解JDBC和JNDI
    JDBC
    Dive into python 实例学python (2) —— 自省,apihelper
  • 原文地址:https://www.cnblogs.com/xiaotie/p/1085834.html
Copyright © 2011-2022 走看看