C# 如何使用RazorGenerator而不是T4来生成C文件?
我希望使用VisualStudio的T4功能,而不是基于我的解决方案的代码模型自动生成C文件/类。我已经使用EnvDTE和T4成功地做到了这一点,但是,我希望使用比T4更易于维护和更好支持的东西C# 如何使用RazorGenerator而不是T4来生成C文件?,c#,envdte,razorgenerator,C#,Envdte,Razorgenerator,我希望使用VisualStudio的T4功能,而不是基于我的解决方案的代码模型自动生成C文件/类。我已经使用EnvDTE和T4成功地做到了这一点,但是,我希望使用比T4更易于维护和更好支持的东西 我试着通过@generator:Template*@使用模板生成器,但是它的输出是带有Execute函数的C类,该函数将生成我需要的模板化C类。如何将C输出直接输入到解决方案中?在解决方案中选择cshtml文件,默认情况下打开属性窗格F4,然后输入RazoGenerator no quotes作为自定义
我试着通过@generator:Template*@使用模板生成器,但是它的输出是带有Execute函数的C类,该函数将生成我需要的模板化C类。如何将C输出直接输入到解决方案中?在解决方案中选择cshtml文件,默认情况下打开属性窗格F4,然后输入RazoGenerator no quotes作为自定义工具。这将在您构建项目时生成一个C源文件 编辑-实际执行生成的类 这更困难,您可能找不到像RazorGenerator这样的预构建自定义工具来为您完成这项工作。我想看看RazorGenerator的源代码,看看他们是如何构建定制工具/扩展方面的。我可能甚至会分叉RazorGenerator代码并修改它以满足我的需要 下面是我用来从razor标记生成类型的方法。这里有一些MVC特有的缺点,您可能可以忽略,例如,添加引用程序集的额外代码,这样编译就不会失败
private Type CompileRazorView(string virtualPath, FileInfo file, Assembly partialViewAssembly)
{
var config = WebConfigurationManager.OpenWebConfiguration("~/Views/web.config");
var section = config.GetSectionGroup("system.web.webPages.razor") as RazorWebSectionGroup;
var host = MvcWebRazorHostFactory.CreateHostFromConfig(section, virtualPath);
var engine = new RazorTemplateEngine(host);
using (var stream = file.OpenRead())
{
using (var reader = new StreamReader(stream))
{
var result = engine.GenerateCode(reader);
string code = null;
using (var tw = new StringWriter())
{
CodeProvider.GenerateCodeFromCompileUnit(result.GeneratedCode, tw, new CodeGeneratorOptions());
tw.Flush();
code = tw.ToString();
}
var compilerParameters = new CompilerParameters()
{
MainClass = host.DefaultClassName,
GenerateInMemory = true,
IncludeDebugInformation = true,
};
var thisAssembly = Application.GetType().Assembly;
var thisAssemblyName = thisAssembly.GetName();
var referencedAssemblies = new List<AssemblyName>();
referencedAssemblies.Add(thisAssemblyName);
referencedAssemblies.Add(partialViewAssembly.GetName());
referencedAssemblies.AddRange(partialViewAssembly.GetReferencedAssemblies());
foreach (var applicationReference in thisAssembly.GetReferencedAssemblies())
{
var assembly = Assembly.Load(applicationReference.FullName);
referencedAssemblies.Add(assembly.GetName());
referencedAssemblies.AddRange(assembly.GetReferencedAssemblies());
}
var binPath = Path.GetDirectoryName(thisAssemblyName.CodeBase);
var distinctReferences = referencedAssemblies.Distinct((a, b) =>
string.Equals(a.FullName, b.FullName, StringComparison.OrdinalIgnoreCase)).ToList();
foreach (var reference in distinctReferences)
{
var referencedAssembly = Assembly.Load(reference.FullName).CodeBase.Substring("file:///".Length);
compilerParameters.ReferencedAssemblies.Add(referencedAssembly);
}
var compilerResults = CodeProvider.CompileAssemblyFromDom(compilerParameters, result.GeneratedCode);
if (compilerResults.Errors.HasErrors)
{
var errorText = new StringBuilder();
foreach (var compilerError in compilerResults.Errors)
{
errorText.AppendLine(compilerError.ToString());
}
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
"The following errors were detected attempting to compile the partial view {0}: \n{1}",
virtualPath, errorText));
}
var typeName = string.Format(CultureInfo.InvariantCulture, "{0}.{1}",
host.DefaultNamespace, host.DefaultClassName);
var type = compilerResults.CompiledAssembly.GetType(typeName);
return type;
}
}
}
该方法将为您提供一个类型,然后您可以使用反射来获得Execute方法,然后您可以调用该方法。诀窍是改变WriteEleral的含义,使其输出到任意流,如cs文件。这只会创建一个.generated.cs文件,其中包含一些围绕一系列WriteEleral调用的样板代码。我希望writeleral的输出被输出到一个.cs文件中。啊,我明白了。您还希望实际执行该类。这不是一项简单的任务。我将编辑我的原始评论,以包含一些代码,让您开始。