Skip to content

Instantly share code, notes, and snippets.

@nikhilk
Created May 3, 2011 06:03
Show Gist options
  • Select an option

  • Save nikhilk/952879 to your computer and use it in GitHub Desktop.

Select an option

Save nikhilk/952879 to your computer and use it in GitHub Desktop.
Single file generator sample/snippet from script# code
// This isn't all the code, but hopefully enough to get you started...
// ResxScriptGenerator.cs
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
namespace ScriptSharp.ResourceModel {
public abstract class ResXScriptGenerator : Interop.IObjectWithSite, Interop.IVsSingleFileGenerator {
private object _site;
private bool _publicResources;
protected ResXScriptGenerator(bool publicResources) {
_publicResources = publicResources;
}
public string GenerateCode(string resourceFileName, string resourceFileContent, string namespaceName) {
if (IsLocalizedResourceFile(resourceFileName)) {
return null;
}
ResourceModelBuilder resourceModelBuilder = new ResourceModelBuilder();
ResourceItemList resourceItems = resourceModelBuilder.BuildResourceItemList(resourceFileContent);
string className = Path.GetFileNameWithoutExtension(resourceFileName);
StringBuilder codeBuilder = new StringBuilder(2048);
codeBuilder.AppendLine("//------------------------------------------------------------------------------");
codeBuilder.AppendLine("// <auto-generated>");
codeBuilder.Append("// ");
codeBuilder.Append(className);
codeBuilder.AppendLine(".cs");
codeBuilder.AppendLine("//");
codeBuilder.Append("// Do not edit directly. This file has been generated by ");
codeBuilder.Append(GetGeneratorName());
codeBuilder.AppendLine(".");
codeBuilder.AppendLine("// </auto-generated>");
codeBuilder.AppendLine("//------------------------------------------------------------------------------");
codeBuilder.AppendLine();
codeBuilder.AppendLine("using System;");
codeBuilder.AppendLine("using System.CodeDom.Compiler;");
codeBuilder.AppendLine("using System.Runtime.CompilerServices;");
codeBuilder.AppendLine();
codeBuilder.Append("namespace ");
codeBuilder.Append(namespaceName);
codeBuilder.AppendLine(" {");
codeBuilder.AppendLine();
codeBuilder.Append(" /// <summary>");
codeBuilder.Append(className);
codeBuilder.AppendLine(" resources class</summary>");
codeBuilder.Append(" [GeneratedCodeAttribute(\"");
codeBuilder.Append(this.GetType().Name);
codeBuilder.Append("\", \"");
codeBuilder.Append(typeof(ResXScriptGenerator).Assembly.GetName().Version.ToString());
codeBuilder.AppendLine("\")]");
codeBuilder.AppendLine(" [Resources]");
codeBuilder.Append(_publicResources ? " public" : " internal");
codeBuilder.Append(" static class ");
codeBuilder.Append(className);
codeBuilder.AppendLine(" {");
foreach (ResourceItem resourceItem in resourceItems.Items) {
codeBuilder.AppendLine();
if (resourceItem.Comment.Length != 0) {
codeBuilder.Append(" /// <summary>");
codeBuilder.Append(resourceItem.Comment);
codeBuilder.AppendLine("</summary>");
}
codeBuilder.Append(" public static readonly string ");
codeBuilder.Append(resourceItem.Name);
codeBuilder.AppendLine(" = null;");
}
codeBuilder.AppendLine(" }");
codeBuilder.AppendLine("}");
return codeBuilder.ToString();
}
private string GetGeneratorName() {
string format;
if (_publicResources) {
format = "PublicResXFileScriptGenerator v{0}";
}
else {
format = "ResXFileScriptGenerator v{0}";
}
Version versionInfo = typeof(ScriptPreprocessorApplication).Assembly.GetName().Version;
return String.Format(format, versionInfo);
}
private static bool IsLocalizedResourceFile(string resourceFileName) {
string locale = Utility.GetResourceFileLocale(resourceFileName);
return (String.IsNullOrEmpty(locale) == false);
}
#region Implementation of IObjectWithSite
int Interop.IObjectWithSite.SetSite(object pUnkSite) {
_site = pUnkSite;
return Interop.S_OK;
}
int Interop.IObjectWithSite.GetSite(ref Guid riid, out IntPtr ppunkSite) {
ppunkSite = IntPtr.Zero;
int hr = Interop.E_FAIL;
if (_site != null) {
IntPtr punk = Marshal.GetIUnknownForObject(_site);
if (punk != IntPtr.Zero) {
try {
hr = Marshal.QueryInterface(punk, ref riid, out ppunkSite);
}
finally {
Marshal.Release(punk);
punk = IntPtr.Zero;
}
}
}
return hr;
}
#endregion
#region IVsSingleFileGenerator Members
int Interop.IVsSingleFileGenerator.GetDefaultExtension(out string extension) {
extension = ".cs";
return Interop.S_OK;
}
int Interop.IVsSingleFileGenerator.Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, out IntPtr pbstrOutputFileContents, out int pbstrOutputFileContentsSize, Interop.IVsGeneratorProgress pGenerateProgress) {
pbstrOutputFileContents = IntPtr.Zero;
pbstrOutputFileContentsSize = 0;
if (String.IsNullOrEmpty(wszInputFilePath)) {
return Interop.E_INVALIDARG;
}
if (String.IsNullOrEmpty(bstrInputFileContents)) {
return Interop.E_INVALIDARG;
}
string code = null;
try {
code = GenerateCode(wszInputFilePath, bstrInputFileContents, wszDefaultNamespace);
}
catch (Exception e) {
Debug.Fail(e.ToString());
}
if (String.IsNullOrEmpty(code)) {
return Interop.E_FAIL;
}
try {
byte[] codeBytes = Encoding.UTF8.GetBytes(code);
IntPtr buffer = Marshal.AllocCoTaskMem(codeBytes.Length);
Marshal.Copy(codeBytes, 0, buffer, codeBytes.Length);
pbstrOutputFileContents = buffer;
pbstrOutputFileContentsSize = codeBytes.Length;
}
catch {
return Interop.E_OUTOFMEMORY;
}
return Interop.S_OK;
}
#endregion
}
}
// Interop.cs
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ScriptSharp {
internal static class Interop {
public const int S_OK = 0;
public const int E_FAIL = unchecked(-2147467259);
public const int E_INVALIDARG = unchecked(-2147024809);
public const int E_OUTOFMEMORY = unchecked(-2147024882);
[
ComImport,
Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
]
internal interface IObjectWithSite {
[PreserveSig]
int SetSite([MarshalAs(UnmanagedType.Interface)] object pUnkSite);
[PreserveSig]
int GetSite([In] ref Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out IntPtr ppunkSite);
}
[
ComImport,
Guid("BED89B98-6EC9-43CB-B0A8-41D6E2D6669D"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
]
internal interface IVsGeneratorProgress {
[PreserveSig]
int GeneratorError(bool fWarning, int dwLevel, [MarshalAs(UnmanagedType.BStr)] string bstrError, int dwLine, int dwColumn);
[PreserveSig]
int Progress(int nComplete, int nTotal);
}
[
ComImport,
Guid("3634494C-492F-4F91-8009-4541234E4E99"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
]
internal interface IVsSingleFileGenerator {
[PreserveSig]
int GetDefaultExtension([Out, MarshalAs(UnmanagedType.BStr)] out string extension);
[PreserveSig]
int Generate([MarshalAs(UnmanagedType.LPWStr)] string wszInputFilePath, [MarshalAs(UnmanagedType.BStr)] string bstrInputFileContents, [MarshalAs(UnmanagedType.LPWStr)] string wszDefaultNamespace, out IntPtr pbstrOutputFileContents, out int pbstrOutputFileContentsSize, IVsGeneratorProgress pGenerateProgress);
}
}
}
// Registration (requires some registry entries ... unfortunately...
// this is done by the script# msi)
// Hopefully WiX code will be indicative of what you need for your own
// single file generator
<RegistryKey Id="VWDExp10_ResxCLSID" Action="createAndRemoveOnUninstall"
Root="HKLM" Key="Software\Microsoft\VWDExpress\9.0\CLSID\{33FA0BF4-CBBA-4fdd-9300-0F5A6BDE7E33}">
<RegistryValue Type="string" Value="ScriptSharp.ResourceModel.ResXInternalScriptGenerator" />
<RegistryValue Type="string" Name="InprocServer32" Value="[%SystemRoot]\System32\mscoree.dll" />
<RegistryValue Type="string" Name="Class" Value="ScriptSharp.ResourceModel.ResXInternalScriptGenerator" />
<RegistryValue Type="string" Name="Assembly" Value="ScriptSharp, Version=[PRODUCTVERSION], Culture=neutral, PublicKeyToken=8fc0e3af5abcb6c4" />
<RegistryValue Type="string" Name="ThreadingModel" Value="Both" />
</RegistryKey>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment