Reflection Studio - 第一部分 - 简介:架构和设计






4.83/5 (23投票s)
Reflection Studio 是一款用于程序集、数据库、性能和代码生成的“开发人员”应用程序,采用 C# 和 WPF 4.0 编写。
引言
在我上一个项目中,我发现没有适用于 .NET 应用程序移动性能测试的软件。那些适用于 WinForms 或 ASP.NET 站点的性能测试软件具有很高的性能成本,因为它们会挂钩它们能挂钩的一切。因此,我决定尝试创建一个基于注入的新软件……但 Reflection Studio 很快就变得不止于此。它是一个围绕我在反射、数据库、代码生成、WPF 等方面所有工作的程序员工具。
Reflection Studio 托管在 http://reflectionstudio.codeplex.com/。它完全使用 C# 在 .NET/WPF 平台下编写。我最近迁移到了 Visual Studio 2010 和 .NET 4。请查看 CodePlex 项目,因为它内容庞大,无法在此详细描述。下面是该应用程序的屏幕截图
目录
由于主题相当庞大,我将(尝试)分几部分来写这篇文章
- 第一部分 - 简介:架构与设计
- 第 2 部分 - 用户界面:主题、对话框、控件、外部库
- 第 3 部分 - 程序集:架构、提供程序和解析、线程与并行、控件
- 第 4 部分 - 数据库:架构、提供程序和插件、控件
- 第 5 部分 - 代码生成:模板、引擎、控件
- 第 6 部分 - 性能:注入、捕获和报告
- 第 7 部分 - 项目 - 整合
第 1 部分 - 架构与设计
1.1 模块
Reflection Studio 包含几个核心模块
- 程序集解析,作为性能注入和创建图表的基础
- 性能注入,用于从任何 .NET 程序集的执行中获取跟踪信息等。
- 代码生成,从模板和数据库等生成代码
- 数据库,架构发现、查询、质量控制、图表等。
1.2 解决方案与程序集
作为项目简介,下面是程序集图,其中蓝色部分是项目程序集
外部程序集
- Moco.Cecil,来自 Mono 项目 - 用于程序集注入
- WPFToolkit,来自 CodePlex - 用于更多控件
- Fluent,来自 CodePlex - 出色的功能区控件库
- AvalonDock,来自 CodePlex - 实现类似 Visual Studio 的界面,带有停靠、面板、工具箱和标签式文档
- ICSharpCode.AvalonEdit - WPF 中的语法高亮编辑器
- WPFVisifire.Charts,来自 CodePlex - 用于图表创建
- ...
内部,我们有以下主要程序集
- ReflectionStudio
- 主要 UI,包含所有特定于 UI 的内容
- ReflectionStudio.Controls
- 所有通用的 UI 相关元素
- ReflectionStudio.Core
- 所有与 UI 或控件无关的业务/核心逻辑和辅助功能
- ReflectionStudio.Core.Database.xxxxProvider
- 用于 SQL 架构发现等的插件程序集
- ReflectionStudio.Spy
- 用于生成性能跟踪的运行时
- ReflectionStudio.Tools
- 用于测试皮肤、颜色和控件的实用工具
类依赖项
Visual Studio 生成的整个类依赖关系图相当难以阅读,但这显示了项目的初始复杂性
总而言之,架构相当简单。我避免使用复杂的模式,类/函数始终遵循相同的原则构建:尽可能简单,并进行异常和跟踪管理。在本文的其余部分,您将详细了解一些“棘手”的部分,例如数据库提供程序、程序集解析器、注入或代码生成引擎。
1.3 跟踪和事件
最初的设想是开发一个既能满足开发人员在我开发过程中的需求,又能很好地更新界面和在所有组件之间共享事件的工具。我不喜欢在代码中编写基本的跟踪,因为它在出现难以解决的问题时很有用,但又难以利用……所以我决定让我的跟踪信息在用户界面中可见。它基于以下模型。
1.3.1 模型:EventDispatcher 和 Tracer
1.3.2 Tracer 类
允许通过经典函数跟踪所有开发步骤,就像在 Microsoft 跟踪或调试系统中一样:Error、Info、Verbose。我通常使用类似下面的模板,这在编写代码和测试时非常有用,因为您可以直接在 UI 中看到跟踪信息
public bool Open( string fileName )
{
Tracer.Verbose("ProjectService:Open", "START");
try
{
Current = new ProjectEntity(fileName);
return LoadProject();
}
catch (Exception err)
{
Tracer.Error("ProjectService.Open", err);
return false;
}
finally
{
Tracer.Verbose("ProjectService:Open", "END");
}
}
Tracer
类的主功能是创建一个消息信息,将其发送到 Microsoft 跟踪系统(如果已配置),然后将其作为消息发送(如果它匹配工作区设置)。
private static void Send(MessageEventType typ, string from, string message)
{
MessageInfo info = new MessageInfo(typ, from, message);
//trace is always used for all levels and can be de-activated in config
Trace.TraceInformation(info.ToString());
//send message only if trace level is under from level toolbox and settings
if (info.Type <= WorkspaceService.Instance.Entity.LogLevel)
EventDispatcher.Instance.RaiseMessage(info);
}
1.3.3 配置
我使用类似下面的函数来配置 Microsoft 跟踪系统。这允许我在每次启动时删除日志,并根据软件设置激活它——在 AppLoad
中调用它
private void TraceConfiguration()
{
try
{
//delete the old log file
string logPath = Path.Combine(PathHelper.ApplicationPath,
"ReflectionStudio.exe.log");
if (File.Exists(logPath))
File.Delete(logPath);
if (ReflectionStudio.Properties.Settings.Default.UseTraceListener)
{
//configure the trace
System.Diagnostics.Trace.AutoFlush = true;
System.Diagnostics.Trace.IndentSize = 2;
//configure the text listener
System.Diagnostics.TraceListenerCollection listeners =
System.Diagnostics.Trace.Listeners;
listeners.Add(new
System.Diagnostics.TextWriterTraceListener(logPath, "LOG"));
}
}
catch (Exception error)
{
Tracer.Error("Reflection Studio.TraceConfiguration", error);
}
}
1.3.4 EventDispatcher 类
它在后台为 Tracer
类提供基本的邮件系统。它可以引发三种类型的事件(所有事件都以消息作为基本信息发送)
Message
:纯文本信息,包含类型、位置、时间等。Status
:带有开始或停止,允许更新状态栏中的进度Project
:更定制化、面向业务,允许发出诸如打开、关闭、保存等事件信号
这是一个使用 EventDispatcher
类来触发项目和状态事件的示例,同时 Tracer
也在 try
/catch
管理中使用。
private bool LoadProject()
{
try
{
EventDispatcher.Instance.RaiseStatus(
Resources.CORE_LOADING, StatusEventType.StartProgress);
EventDispatcher.Instance.RaiseProject(Current, ProjectEventType.Opening);
Current = new ProjectDAC().Load(Current.ProjectFilePath);
if (Current != null)
{
//refresh by assembly parsing
Refresh();
EventDispatcher.Instance.RaiseProject(Current, ProjectEventType.Opened);
return true;
}
else
{
EventDispatcher.Instance.RaiseStatus(Resources.CORE_LOADING_ERROR,
StatusEventType.StopProgress);
return false;
}
}
catch (Exception err)
{
Tracer.Error("ProjectService.LoadProject", err);
return false;
}
finally
{
EventDispatcher.Instance.RaiseStatus(Resources.CORE_PROJECT_LOADED,
StatusEventType.StopProgress);
}
}
1.3.5 日志工具箱
为了完善这一切,我必须编写一个控件来在 UI 中显示它。我不是凭空创造,而是以 Visual Studio 为榜样。因此,我创建了一个 LogToolBox
用户控件,并将其插入到 Avalon 内容中。使用转换器将消息类型更改为错误图标会很棒!
1.3.6 连接
为了让所有这一切正常工作,您只需要像我在主窗口创建时那样将事件处理程序连接在一起
//catch events
EventDispatcher.Instance.OnProjectChange +=
new EventHandler<ProjectEventArgs>(OnProjectChange);
EventDispatcher.Instance.OnStatusChange +=
new EventHandler<StatusEventArgs>(this.MainStatusBar.OnStatusChange);
//forward also all changes to the log toolbox
EventDispatcher.Instance.OnMessage +=
new EventHandler<MessageEventArgs>(this.LogToolbox.OnMessage);
1.4 辅助功能
1.4.1 序列化
核心程序集包含一个辅助类,用于将任何类型的对象序列化或反序列化为二进制或 XML 格式。它非常简单,就像这样:
//Deserialize
entity = (WorkspaceEntity)SerializeHelper.Deserialize(WorkspaceFile,
typeof(WorkspaceEntity), false);
//Serialize
result = SerializeHelper.Serialize(WorkspaceFile, entity, false);
1.4.2 各种辅助功能
核心程序集还包含:
UrlSave
和AsyncUrlSave
,用于保存任何 HTTP GET 的响应ByteHelper
和CecilHelper
ResourceHelper
:读取嵌入式资源ProcessHelper
:启动浏览器访问 Web URIWorkerBase
,用于管理BackgroundWorker
以实现多线程
1.5 文档
所有代码都需要用英语进行文档记录,因为我启用了 XML 文档。这使得 Sandcastle 和 Sandcastle Help File Builder 能够生成新 2010 Help Viewer 格式的技术项目帮助文件。它包含在源代码中,可以通过构建解决方案文件夹 <ReflectionStudio\Documents\Help> 中的 RSHelp.shfbproj 来生成和安装。由于体积太大,它将不包含在源代码或发行版中。
此外,我尽量为每个版本更新用户手册和技术文档。您可以在 <Help> 文件夹中找到它们,格式为 doc 或 xps 文档,或者通过应用程序中的主功能区选项卡查看下面的帮助文档插图。
1.6 安装
设置和相关项目自 Beta 0.2 版本以来已经创建。但是可能会有很多更改;请不要忘记卸载任何先前的安装,我们不保证在首次发布前版本之间的项目可逆性。
所有内容都安装在 Reflection Studio 文件夹中。对计算机没有特殊需求,也没有修改要求。
结论/反馈
下一篇文章再见。请不要犹豫,就此文在 CodePlex 或 CodeProject 上给我反馈。随着团队的壮大,我希望我们的发展速度会更快,不要犹豫加入我们!
文章/软件历史
- 初始发布 - 版本 BETA 0.2
- 包含“几乎”所有功能的初始版本,可在第 1 部分或 CodePlex 下载
- 版本 BETA 0.3
- 更新了皮肤/颜色管理和数据库模块。
- 第四部分 - 数据库模块 - 已发布。