原创 SharpDevelop源代码分析笔记

2009-11-16 18:50 3391 7 7 分类: 软件与OS
1.如何创建插件树
 CoreStartup的RunInitialization调用AddInTree.Load方法,加载Addins,并执行/Workspace/Autostart节点下的Addin的Command
 加
载Addins时,XmlReader解析.addin文件,调用了AddIn.Load,AddIn.SetupAddIn,根据xml元素是
Runtime,Include,Path,Manifest等,分别解析,填充到AddIn对象 例如Path,调用
ExtensionPath.SetUp方法(递归),会解析并创建下层所有Codon对象,添加到ExtensionPath对象中。
 AddInTree.Load
方法调用AddInTree.InsertAddIn方法添加每一个AddIn到插件树中:对AddIn中的每一个Path,首先创建
AddInTreeNode,然后把之前解析存放在ExtensionPath中的Codon列表拷贝到AddInTreeNode对象,
 这样,整个插件数就创建起来了。

2.如何获得插件实例
 调用AddInTree.BuildItem(一个Codon)/BuildItems(AddInNode下所有Codon)方法。
 BuildItem方法首先分析出AddInTreeNode,创建出这个节点下的Codon对象,再根据Codon的id查找需要的插件实例。
 AddInTree.BuildItems -> AddInTreeNode.BuildChildItems(递归) -> Codon.BuildItem -> IDoozer.BuildItem
 实例化的Codon存放在什么地方?


3.Doozer,Codon,addin
 Doozer提供实例化Codon的方法,Codon与Doozer的关系相当于Object与Class的关系。SD中所有的资源包括Menu,Toolbar,Icon,String,Pad,Dialog等都可在.addin中描述,用对应的Doozer实例化。


4.Service
 提供功一些通用的操作,是static或Singleton的,它在各个addin之间起到的粘合的作用
 MenuService提供了从Addin树创建菜单的功能,
 ToolBarService提供了从Addin树创建工具栏的功能,
 LoggingService调用log4net记录日志
 FileUtility提供通用的文件操作
 PropertyService提供全局属性关系,包括属性的持久化
 ResourceService提供资源的管理
 MessageService显示消息给用户


5.ICSharpCode.SharpDevelop工程
 位于Main/Base目录,是应用程序的基础Addin,Core工程提供的组织插件的方法,SharpDevelop也只是在Core之上的一个插件。但它提供了一些基本的功能供其余插件使用。
 SharpDevelop提供了控制应用程序主窗口的代码,提供了主要功能的接口,例如:管理,撤销/重做,pad(可停靠的面板)


6.初始化过程
 [StartUp]->(SharpDevelopMain.cs).RunApplication
   创建并设置StartupSettings,SharpDevelopHost,WorkbenchSettings,调用SharpDevelopHost.RunWorkbench
   在
SharpDevelopHost的构造函数中,调用CallHelper.InitSharpDevelopCore方法初始化Core(调用了
Core工程中的CoreStartup的StartCoreServices和RunInitialization方法,创建Addin树)
 [SharpDevelop.Sda]->(SharpDevelopHost.cs).RunWorkbench
   创建新的AppDomain,让Workbench在这里面运行,为什么这么做?
 [SharpDevelop.Sda]->(CallHelper.cs).RunWorkbench
   决定是否创建新的线程,让workbench在新线程中运行
 [SharpDevelop.Sda]->(CallHelper.cs).RunWorkbenchInternal
   调用WorkbenchSingleton.InitializeWorkbench(),创建主界面DefaultWorkbench,调用DefaultWorkbench.InitializeWorkspace初始化主界面,初始化各种服务
   触发CallHelper的BeforeRunWorkbench事件;
   主界面退出后,触发CallHelper的WorkbenchClosed事件;
 [SharpDevelop]->(Commands/AutostartCommands.cs).Run
 Application.Run(WorkbenchSingleton.MainForm)
   WorkbenchSingleton是单例模式的,包含DefaultWorkbench,是主界面


7.使用Core的例子


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 主函数:


   // The LoggingService is a small wrapper around log4net.
   // Our application contains a .config file telling log4net to write
   // to System.Diagnostics.Trace.
   LoggingService.Info("Application start");
   
   // Get a reference to the entry assembly (Startup.exe)
   Assembly exe = typeof(Program).Assembly;
   
   // Set the root path of our application. ICSharpCode.Core looks for some other
   // paths relative to the application root:
   // "data/resources" for language resources, "data/options" for default options
   FileUtility.ApplicationRootPath = Path.GetDirectoryName(exe.Location);
   
   LoggingService.Info("Starting core services...");
   
   // CoreStartup is a helper class making starting the Core easier.
   // The parameter is used as the application name, e.g. for the default title of
   // MessageService.ShowMessage() calls.
   CoreStartup coreStartup = new CoreStartup("Test application");
   // It is also used as default storage location for the application settings:
   // "%Application Data%\%Application Name%", but you can override that by setting c.ConfigDirectory
   
   // Specify the name of the application settings file (.xml is automatically appended)
   coreStartup.PropertiesName = "AppProperties";
   
   // Initializes the Core services (ResourceService, PropertyService, etc.)
   coreStartup.StartCoreServices();
   
   // Registeres the default (English) strings and images. They are compiled as
   // "EmbeddedResource" into Startup.exe.
   // Localized strings are automatically picked up when they are put into the
   // "data/resources" directory.
   ResourceService.RegisterNeutralStrings(new ResourceManager("Startup.StringResources", exe));
   ResourceService.RegisterNeutralImages(new ResourceManager("Startup.ImageResources", exe));
   
   LoggingService.Info("Looking for AddIns...");
   // Searches for ".addin" files in the application directory.
   coreStartup.AddAddInsFromDirectory(Path.Combine(FileUtility.ApplicationRootPath, "AddIns"));
   
   // Searches for a "AddIns.xml" in the user profile that specifies the names of the
   // add-ins that were deactivated by the user, and adds "external" AddIns.
   coreStartup.ConfigureExternalAddIns(Path.Combine(PropertyService.ConfigDirectory, "AddIns.xml"));
   
   // Searches for add-ins installed by the user into his profile directory. This also
   // performs the job of installing, uninstalling or upgrading add-ins if the user
   // requested it the last time this application was running.
   coreStartup.ConfigureUserAddIns(Path.Combine(PropertyService.ConfigDirectory, "AddInInstallTemp"),
                                   Path.Combine(PropertyService.ConfigDirectory, "AddIns"));
   
   LoggingService.Info("Loading AddInTree...");
   // Now finally initialize the application. This parses the ".addin" files and
   // creates the AddIn tree. It also automatically runs the commands in
   // "/Workspace/Autostart"
   coreStartup.RunInitialization();
   
   LoggingService.Info("Initializing Workbench...");
   // Workbench is our class from the base project, this method creates an instance
   // of the main form.
   Workbench.InitializeWorkbench();
   
   try {
    LoggingService.Info("Running application...");
    // Workbench.Instance is the instance of the main form, run the message loop.
                Application.Run(Workbench.Instance);
   } finally {
    try {
     // Save changed properties
     PropertyService.Save();
    } catch (Exception ex) {
     MessageService.ShowError(ex, "Error storing properties");
    }
   }
   
   LoggingService.Info("Application shutdown");


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 主界面:
 
 public partial class Workbench : Form
    {
        static Workbench instance;


        public static Workbench Instance
        {
            get
            {
                return instance;
            }
        }


        public static void InitializeWorkbench()
        {
            instance = new Workbench();
        }


        MenuStrip menu;
        ToolStrip toolbar;
        Panel contentPanel;


        private Workbench()
  {
   //
   // The InitializeComponent() call is required for Windows Forms designer support.
   //
   InitializeComponent();
   
   //
   // TODO: Add constructor code after the InitializeComponent() call.
   //
            contentPanel = new Panel();
            contentPanel.Dock = DockStyle.Fill;
            this.Controls.Add(contentPanel);


            menu = new MenuStrip();
            MenuService.AddItemsToMenu(menu.Items, this, "/Workbench/MainMenu");


            toolbar = ToolbarService.CreateToolStrip(this, "/Workbench/Toolbar");


            this.Controls.Add(toolbar);
            this.Controls.Add(menu);
  }
 } 
 
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////


 AddIn:
 <AddIn name        = "Demo Application"
       author      = "Daniel Grunwald"
       url         = "http://www.codeproject.com/TBD"
       description = "Base add-in of ICSharpCode.Core example"
       addInManagerHidden = "true">
 
 <Manifest>
  <!-- unique name of the AddIn, used when others AddIns want to reference this AddIn -->
  <Identity name="MainForm" version = "1.0.0.0"/>
  <!--
  others AddIns can specify dependencies like this:
  <Dependency addin="ICSharpCode.Core.Demo" version="1.0.0.x-1.0.0.y"/>
  -->
 </Manifest>
 
 <Runtime>
  <Import assembly = "../MainForm.exe"/>
 </Runtime>
 
 <Path name = "/Workspace/FileFilter">
  <FileFilter id = "Text" name = "Text files" extensions = "*.txt"/>
  <FileFilter id = "LogFiles" name = "Log files" extensions = "*.log"/>
 </Path>
 
 <Path name = "/Workspace/DisplayBindings">
  <Class id = "Text" class = "Base.TextDisplayBinding"/>
 </Path>
 
 <Path name = "/Workspace/Tools">
 </Path>
 
 <Path name = "/Workbench/MainMenu">
  <MenuItem id = "File"
            type = "Menu"
            label = "文件(&amp;F)">
   <MenuItem id = "New"
             label = "新建&amp;N"
             shortcut = "Control|N"
            
             class = "MainForm.NewFileCommand"/>
   <MenuItem id = "Open"
             label = "打开(&amp;O)"
             shortcut = "Control|O"
             icon = "Icons.Open"
             class = "MainForm.OpenFileCommand"/>
   <MenuItem id = "Save"
             label = "&amp;Save"
             shortcut = "Control|S"
            
             class = "MainForm.SaveFileCommand"/>
   <MenuItem id = "SaveAs"
             label = "&amp;Save as..."
             class  = "Base.SaveFileAsCommand"/>
   <MenuItem id = "Separator1" type = "Separator"/>
   <MenuItem id = "Exit"
             label = "&amp;Exit"
             class = "MainForm.ExitCommand"/>
  </MenuItem>
  <MenuItem id = "Tools"
            type = "Menu"
            label = "&amp;Tools">
   <Include id = "ToolList" path = "/Workspace/Tools"/>
  </MenuItem>
  <MenuItem id = "Help"
            type = "Menu"
            label = "&amp;?">
   <MenuItem id = "Info"
             label = "&amp;Info..."
             icon = "Icons.Help"
             class  = "Base.InfoCommand"/>
  </MenuItem>
 </Path>
 
 <Path name = "/Workbench/Toolbar">
  <ToolbarItem id = "New"
               tooltip = "Create new text file"
                 label = "&amp;New"
               class = "Base.NewFileCommand"/>
  <ToolbarItem id = "Open"
               tooltip = "Open existing file"
              
               class  = "Base.OpenFileCommand"/>
  <ToolbarItem id = "Save"
               tooltip = "Save the current file"
              
               class  = "Base.SaveFileCommand"/>
  <ToolbarItem id = "Separator1" type = "Separator"/>
  <ToolbarItem id = "Info"
               tooltip = "Show about dialog"
              
               class  = "Base.InfoCommand"/>
 </Path>
</AddIn>


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////


8.国际化
 由ResourceService完成,负责载入各种语言对应的资源文件。
 在初始化时,添加默认的资源:
            ResourceService.RegisterNeutralStrings(new ResourceManager("Entry.myRes", asm));
            ResourceService.RegisterNeutralImages(new ResourceManager("Entry.myRes", asm));
  同时,根据properties文件中的CoreProperties.UILanguage找到语言环境,从data/resoureces目录找到对应的resources文件,读取字符串和图片资源放入HashTable中

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
7
关闭 站长推荐上一条 /3 下一条