2

Visual Studio の T4 機能の代わりにhttp://razorgenerator.codeplex.com/を使用して、ソリューションのコード モデルに基づいて C# ファイル/クラスを自動生成したいと考えています。T4 で EnvDTE を使用してこれを成功させましたが、T4 よりも保守が容易でサポートが優れているものを使用したいと考えています。

経由でテンプレート ジェネレーターを使用してみまし@* Generator: Template *@たが、その出力は、Execute必要なテンプレート化された c# クラスを生成する関数を含む C# クラスです。C# の出力をソリューションに直接取り込むにはどうすればよいですか?

4

1 に答える 1

0

ソリューションで 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 メソッドに到達し、それを呼び出すことができます。トリックは、cs ファイルのような任意のストリームに出力されるように、WriteLiteral の意味を変更することです。

于 2013-06-19T19:16:57.000 に答える