VsSingleFileGenerator插件创建,安装和使用

    相信很多用过VS朋友都会发现一个问题,就是当编写一个XML或一个资源文件的时候VS会为该文件同时生成个类文件;其实我们也可以针对某种文件来实现自定义的生成效果,这种插件就是VS提供给相关文件的自定义工具功能(Custom Tools);下面将为大家介绍如何构造一个VsSingleFileGenerator插件,制作安装发布和在VS中使用.

编写插件

首先要知道的编写这样一个插件需要什么,其实这东西在Google一搜应该就有不少资料和相关sample,直接拿下来看下基本知道原来.编写这样一个插件所需要用到的是一个接口IVsSingleFileGenerator,对于这个接口的详细介绍可以通过MSDN了解.下面看一下实现这接口后的对象代码是怎样的

ContractedBlock.gif ExpandedBlockStart.gif View Code
  1 /// <summary>
2 ///
3 /// </summary>
4 [Guid("F9135C1D-E958-485b-95B9-0233E63930ED")]
5 public class InterfaceToModel : IVsSingleFileGenerator, VSOLE::IObjectWithSite
6 {
7 private CodeDomProvider codeProvider;
8
9 private string codeFileNameSpace;
10 private string codeFilePath;
11
12 private object site;
13
14 private IVsGeneratorProgress codeGeneratorProgress;
15
16 public CodeDomProvider CodeProvider
17 {
18 get
19 {
20 if (this.codeProvider == null)
21 {
22 codeProvider = CodeDomProvider.CreateProvider("C#");
23 }
24
25 return this.codeProvider;
26 }
27
28 set
29 {
30 if (value == null)
31 {
32 throw new ArgumentNullException();
33 }
34
35 this.codeProvider = value;
36 }
37 }
38
39 #region IVsSingleFileGenerator Members
40
41 public int DefaultExtension(out string ext)
42 {
43 string defExt;
44 ext = string.Empty;
45
46 defExt = this.CodeProvider.FileExtension;
47
48 if (((defExt != null) && (defExt.Length > 0)) && (defExt[0] != '.'))
49 {
50 defExt = "." + defExt;
51 }
52
53 if (!string.IsNullOrEmpty(defExt))
54 {
55 ext = ".Model" + defExt;
56 }
57
58 return 0;
59 }
60
61 public int Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] pbstrOutputFileContents, out uint pbstrOutputFileContentSize, IVsGeneratorProgress pGenerateProgress)
62 {
63 if (bstrInputFileContents == null)
64 {
65 throw new ArgumentNullException(bstrInputFileContents);
66 }
67
68 this.codeFilePath = wszInputFilePath;
69 this.codeFileNameSpace = wszDefaultNamespace;
70 this.codeGeneratorProgress = pGenerateProgress;
71
72 byte[] generatedStuff = this.GenerateCode(wszInputFilePath, bstrInputFileContents);
73
74 if (generatedStuff == null)
75 {
76 pbstrOutputFileContents[0] = IntPtr.Zero;
77 pbstrOutputFileContentSize = 0;
78 }
79 else
80 {
81 pbstrOutputFileContents[0] = Marshal.AllocCoTaskMem(generatedStuff.Length);
82 Marshal.Copy(generatedStuff, 0, pbstrOutputFileContents[0], generatedStuff.Length);
83 pbstrOutputFileContentSize = (uint)generatedStuff.Length;
84 }
85 return 0;
86 }
87 #endregion
88
89 #region IObjectWithSite Members
90
91 public void GetSite(ref Guid riid, out IntPtr ppvSite)
92 {
93 if (this.site == null)
94 {
95 throw new Win32Exception(-2147467259);
96 }
97
98 IntPtr objectPointer = Marshal.GetIUnknownForObject(this.site);
99
100 try
101 {
102 Marshal.QueryInterface(objectPointer, ref riid, out ppvSite);
103 if (ppvSite == IntPtr.Zero)
104 {
105 throw new Win32Exception(-2147467262);
106 }
107 }
108 finally
109 {
110 if (objectPointer != IntPtr.Zero)
111 {
112 Marshal.Release(objectPointer);
113 objectPointer = IntPtr.Zero;
114 }
115 }
116 }
117
118 public void SetSite(object pUnkSite)
119 {
120 this.site = pUnkSite;
121 this.codeProvider = null;
122 }
123
124 #endregion
125
126 #region Private Methods
127 protected byte[] GenerateCode(string inputFileName, string inputFileContent)
128 {
129 using (System.IO.FileStream stream =System.IO.File.Open(inputFileName, FileMode.Open, FileAccess.Read))
130 {
131 Smark.Data.InterfaceToModelGenerator.GenerateCode gc
132 = new GenerateCode();
133 return StreamToBytes(gc.Builder(stream));
134 }
135
136 }
137
138 protected byte[] StreamToBytes(Stream stream)
139 {
140 if (stream.Length == 0)
141 {
142 return new byte[0];
143 }
144
145 long pos = stream.Position;
146
147 stream.Position = 0;
148
149 byte[] buffer = new byte[(int)stream.Length];
150 stream.Read(buffer, 0, buffer.Length);
151
152 stream.Position = pos;
153 return buffer;
154 }
155
156 private void ThrowOnFailure(int hr)
157 {
158 if ((hr < 0))
159 {
160 Marshal.ThrowExceptionForHR(hr);
161 }
162 }
163 #endregion
164 }

其实整个类的实现都比较简单,主要有两个方法是需要我们去关注分别是:

 public int DefaultExtension(out string ext)

这个方法主要是描述生成文件的默认后缀扩展名

public int Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] pbstrOutputFileContents, out uint pbstrOutputFileContentSize, IVsGeneratorProgress pGenerateProgress)

 这个方法比重要,主要是获取当前文件路径,名称空间,输出文件内容等相关信息;并根据根据这些信息按实际需要生成相关文件内容输出给相关参数.

byte[] generatedStuff = this.GenerateCode(wszInputFilePath, bstrInputFileContents);

if (generatedStuff == null)
{
pbstrOutputFileContents[0] = IntPtr.Zero;
pbstrOutputFileContentSize = 0;
}
else
{
pbstrOutputFileContents[0] = Marshal.AllocCoTaskMem(generatedStuff.Length);
Marshal.Copy(generatedStuff, 0, pbstrOutputFileContents[0], generatedStuff.Length);
pbstrOutputFileContentSize = (uint)generatedStuff.Length;
}
return 0;
 从上面代码可以看到,Generate方法内部所做的事情就是根据需要生成一个文件内容generatedStuff,并根据generatedStuff数据情况进行参数更新,告诉VS如何处理.

     大概看一下this.GenerateCode方法做得是什么:

protected byte[] GenerateCode(string inputFileName, string inputFileContent)
{
using (System.IO.FileStream stream =System.IO.File.Open(inputFileName, FileMode.Open, FileAccess.Read))
{
Smark.Data.InterfaceToModelGenerator.GenerateCode gc
= new GenerateCode();
return StreamToBytes(gc.Builder(stream));
}

}
public System.IO.Stream Builder(System.IO.Stream stream)
{
System.IO.StringWriter sw = new System.IO.StringWriter();
Console.SetOut(sw);
Console.SetError(sw);
CSharpParser p = new CSharpParser(null, stream, null);
System.IO.Stream result = new System.IO.MemoryStream();
System.IO.StreamWriter writer = new System.IO.StreamWriter(result, Encoding.UTF8);
int errno = p.parse();
if (errno > 0)
{
writer.Write(sw.ToString());
}
CodeCompileUnit unit = p.Builder.CurrCompileUnit;

if (unit != null)
{
try
{
Microsoft.CSharp.CSharpCodeProvider csp = new Microsoft.CSharp.CSharpCodeProvider();
foreach (string assembly in unit.ReferencedAssemblies)
{
mEntityUnit.ReferencedAssemblies.Add(assembly);
}

foreach (CodeNamespace cn in unit.Namespaces)
{
BuilderNameSpace(cn);
}
csp.GenerateCodeFromCompileUnit(mEntityUnit, writer, new CodeGeneratorOptions());
writer.Flush();
}
catch (Exception e_)
{
writer.WriteLine(e_.Message + e_.StackTrace);
}
}
return result;

}

其实就是生成文件内容并返回相关流数据

 制作安装

     插件使用必须要把相关类信息注册到win注册表中让vs可以识别,还要把类生成的程序集部署到全局程序集中,这样做的前提就是要给程序集签名并发为相关类生成uid标识(对于这些详细信息可以通过MSDN了解).以上工作其实可以手动去做自行导入注册表和copy文件到全局目录中;这种做法确实比较山寨,我们可以创建一个安装项目,生成相关安装程序自动地完成这些事情.

 首先把需要的DLL添加到GAC中 

然后针对不同VS需要的版本构造相关的注册信息,也可以通过现有的注册项文件导入

以上工作都做好后,直接编译生成安装文件包就OK了.

使用插件

 其实插件使用也很简单,只需要在文件属性的自定义工具处理,填写插件制定的名称就行了

插件源码

http://smark.codeplex.com/

转载于:https://www.cnblogs.com/smark/archive/2011/10/13/2210432.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
截至2011年11月27日Reflector真正的最新版本(其它声明比本版本高的版本号均是假的,可到Reflector官网查询),已经注册的绿色版本。真正集成了 FileDisassembler FileGenerator 两个最流行的插件!! NET程序员必备的开发利器.NET Reflector   Reflector是一款比较强大的反编译工具,相信很多朋友都用过它,但reflector本身有很多局限性,比如只能一个一个的查看方法等,但 幸好reflector支持插件功能目前网上有很多reflector的插件,本人找取了两个应用范围很广,并且广受好评的插件: Reflector.FileDisassembler和Reflector.FileGenerator和Reflector进行了整合,放在了一个压 缩包中,大家可以直接解压缩后就开始使用,其中FileGenerator在网上没有现成dll,本人编译后将其取出,放在了压缩包中,一直在苦苦找寻的 朋友这次可以拿来直接用了 本压缩包中Reflector.exe已经升级为最新的7.4版本,具体的使用方法不多说了,只简单介绍一下本压缩包的使用步骤: 先 下载本压缩包并解压缩,运行其中的Reflector.exe(主程序),初次运行会弹出错误提示对话框,因为引用的两个插件DLL是按照我本地实际情况 配置的,所以你还需要根据你的实际情况来从新配置一下,方法很简单,我们拿引用FileGenerator.dll来做一个范例, 首先介绍一下 Filegenerator,FileGenerator插件的作用是:根据dll文件,把里面的源文件导出成文件,导出来的文件除了没有注释,变量名也 变了,其它的可谓是没有差别。对于一些比较好的控件,如果不是开源的,完全可以导出成文件,然后自己加上注释,少许修改,很好的利用起来。(不开源的 dll,用起来也不放心啊) 具体的初始化设置方法:点击View->Add-Ins...,弹出一个窗口,然后点击Add->选择文件夹里面的:"FileGenerator.dll",点击close. 然后回到Reflector窗口,Tool->Generator File(s)... 右边就出现了插件的窗口,选中左边的dll文件,点击右边的导出文件,源代码就全部导出来了!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值