簡體   English   中英

如何使用RazorGenerator而不是T4生成C#文件?

[英]How can I use RazorGenerator instead of T4 for generating C# files?

我想使用http://razorgenerator.codeplex.com/代替Visual Studio的T4功能根據我的解決方案的代碼模型自動生成C#文件/類。 我已經在T4上使用EnvDTE成功完成了此操作,但是,我想使用比T4更可維護和更好支持的功能。

我嘗試通過@* Generator: Template *@使用Template生成@* Generator: Template *@ ,但是從中得到的輸出是帶有Execute函數的C#類,該函數將生成我需要的模板化c#類。 如何將C#輸出直接輸入到解決方案中?

在解決方案中選擇cshtml文件,打開屬性窗格(默認為F4),然后輸入“ RazorGenerator”(不帶引號)作為自定義工具。 當您構建項目時,這將生成一個C#源文件。

編輯-實際也執行生成的類

這更加困難,並且您可能找不到像RazorGenerator這樣的預制自定義工具來為您完成此任務。 我將看一下RazorGenerator的源代碼,以了解他們如何構建自定義工具/擴展方面。 我可能甚至可以擴展RazorGenerator代碼並對其進行修改以滿足我的需要。

這是我用來從剃刀標記生成Type的方法。 這是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;

                }
            }
        }

此方法將為您提供一個Type,您可以將其與反射一起使用,以實現Execute方法,然后可以調用該方法。 訣竅將是改變WriteLiteral的含義,以使其輸出到任意流,例如cs文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM