質問

これが最初に質問です:

これは可能ですか?私は私のインスピレーションを取得しています Joe Wrobelの作品 (忘れられた人のredux CodePlexプロジェクト)。ここでは、プロバイダーのプロフィールを作成する作業を行い、それが強力なタイピングを作成し、プロファイルクラスのファサードを効果的に作成するという段階を実行します。

そして今、バックストーリー!

私は本当に好きではありません 魔法の弦. 。それらはかなり悪いものであり、アプリケーションの更新に関していくつかの深刻な問題を引き起こす可能性があります。 PHPやColdFusionなどの言語で働いていたので、アプリケーションに簡単に配置して、変更する必要があるまで忘れることは簡単であることを知っています。そして、あなたはそれらのすべてのバリエーションを狩り、それに応じてそれらを変更する必要があります。

.NETは、「ボックスから外れた」アプリケーションテンプレートをフォローしていれば、それほど良くありません。多くの例は、web.configのappsettingsを使用して、さまざまな設定を保存しています。これは確かに保管するのに最適な場所であり、ほとんどのアプリケーションに最適です。ただし、これらを直接呼び出し始めると問題が発生し始めます - たとえば ConfigurationManager.AppSettings["MyAppSetting"]. 。そうすれば、魔法の文字列を使用することに戻っているので、PHPユーザーよりも優れていません。

これがここです ファサード 入ってください。ファサードは、1つの場所で魔法の弦から強くタイプのオブジェクトを作成し、開発者にアプリケーションの残りの部分からそれを参照する方法を提供します。

これで、web.configを使用してAppSettingsを含める代わりに、データベースを使用してすべてを保持します。アプリケーションの開始時に、名前/値コンボが取得され、次に順次追加されます ConfigurationManager.AppSettings 経由 Set. 。大物はありません(以外は 問題 私は以前に持っていました!)。

この「アプリケーションファサード」は、データレイヤー、サービスレイヤー、プレゼンテーションレイヤーによってアクセスでき、アプリケーションモードのようなものを保持します。これは、Yada Yada Yadaを使用するサービスエンドポイントを保持し、多くの魔法の弦を狩る必要性を制限します。文字列 - ファサードの1つ(名前)、もう1つ(名前と価値)が作成のポイント(私にとってはDBです)。

このファサードクラスは最終的にかなり大きくなり、最終的には両方を更新しなければならないことに飽きます。

したがって、私がやりたいのは、ビルドが完了するたびに自動生成するApplicationFacadeクラスを用意することです。そして今、最初に戻って...これは可能ですか?

役に立ちましたか?

解決

この目的のためにCodeSmithテンプレートを使用することもできます。利点は、各ビルドで再生されるテンプレートファイルプロパティを設定できることです(buildaction = "Compleile")

編集私もそのような解決策を探しました。グーグル後、私はそのようなクラスを生成するためのベースT4テンプレートを見つけました。私はそれを再設計しました、そしてあなたはそれを以下に見つけることができます。

テンプレートは、web.config/app.configファイルからセクションをAppSettingセクションのラッパークラスを生成しています

構成ファイルに次の設定行があるとします

  <appSettings>
    <add key="PageSize" value="20" />
    <add key="CurrentTheme" value="MyFavouriteTheme" />
    <add key="IsShowSomething" value="True" />
  </appSettings>

テンプレートを処理すると、次のクラスが表示されます

namespace MyProject.Core
{
    /// <remarks>
    /// You can create partial class with the same name in another file to add custom properties
    /// </remarks>
    public static partial class SiteSettings 
    {
        /// <summary>
        /// Static constructor to initialize properties
        /// </summary>
        static SiteSettings()
        {
            var settings = System.Configuration.ConfigurationManager.AppSettings;
            PageSize = Convert.ToInt32( settings["PageSize"] );
            CurrentTheme = ( settings["CurrentTheme"] );
            IsShowSomething = Convert.ToBoolean( settings["IsShowSomething"] );
        }

        /// <summary>
        /// PageSize configuration value
        /// </summary>
        public static readonly int PageSize;

        /// <summary>
        /// CurrentTheme configuration value
        /// </summary>
        public static readonly string CurrentTheme;

        /// <summary>
        /// IsShowSomething configuration value
        /// </summary>
        public static readonly bool IsShowSomething;

    }
}

次のコードを *.ttファイルに保存します 生成されたファイルを配置する場所にプロジェクトに含めます。各ビルドでクラスを再生します ここで私の答えをご覧くださいテンプレートは、値から文字列、datetime、int、およびboolタイプを認識します

<#@ assembly name="System.Core" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Xml.Linq" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Xml.Linq" #>
<#@ import namespace="Microsoft.VisualBasic" #>
<#@ template language="VB" debug="True" hostspecific="True"  #>
<#@ output extension=".Generated.cs" #>
<#
    Dim projectNamespace as String = "MyProject.Core"
    Dim className as String = "SiteSettings"
    Dim fileName as String = "..\..\MyProject.Web\web.config"

    Init(fileName)  

#>
//------------------------------------------------------------------------------
// FileName = <#= path #>
// Generated at <#= Now.ToLocaltime() #>
//
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
//     
//    NOTE: Please use the Add a Reference to System.Configuration assembly if 
//          you get compile errors with ConfigurationManager
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Configuration;

namespace <#= projectNamespace #>
{
    /// <remarks>
    /// You can create partial class with the same name in another file to add custom properties
    /// </remarks>
    public static partial class <#= className #> 
    {
        /// <summary>
        /// Static constructor to initialize properties
        /// </summary>
        static <#= className #>()
        {
            var settings = System.Configuration.ConfigurationManager.AppSettings;
<#= AddToCostructor(path) #>        }

<#= RenderApplicationSettings(path) #>  }
}

<#+ 
    Dim path as String = ""
    Dim doc as XDocument = Nothing

    Public Sub Init(fileName as String)
        Try
            path = Host.ResolvePath(fileName)
            If File.Exists(path) Then
                doc = XDocument.Load(path)
            End If
        Catch
            path = "<< App.config or Web.config not found within the project >>"
        End Try     
    End Sub

    Public Function AddToCostructor(ByVal path as String) as String                 
        If doc Is Nothing Then Return ""

        Dim sb as New StringBuilder()

        For Each result as XElement in doc...<appSettings>.<add>            
            sb.Append(vbTab).Append(vbTab).Append(vbTab)
            sb.AppendFormat("{0} = {1}( settings[""{0}""] );", result.@key, GetConverter(result.@value))
            sb.AppendLine()
        Next

        Return sb.ToString()

    End Function

    Public Function RenderApplicationSettings(ByVal path as String) as String
        If doc Is Nothing Then Return ""

        Dim sb as New StringBuilder()       

        For Each result as XElement in doc...<appSettings>.<add>    
            dim key = result.@key
            sb.Append(vbTab).Append(vbTab)
            sb.Append("/// <summary>").AppendLine()
            sb.Append(vbTab).Append(vbTab)
            sb.AppendFormat("/// {0} configuration value", key).AppendLine()            
            sb.Append(vbTab).Append(vbTab)
            sb.Append("/// </summary>").AppendLine()
            sb.Append(vbTab).Append(vbTab)
            sb.AppendFormat("public static readonly {0} {1}; ", GetPropertyType(result.@value), key)    
            sb.AppendLine().AppendLine()
        Next

        Return sb.ToString()

    End Function

    Public Shared Function GetConverter(ByVal prop as String) as String     
        If IsNumeric(prop) Then Return "Convert.ToInt32"
        If IsDate(prop) Then Return "Convert.ToDateTime"
        dim b as Boolean
        If Boolean.TryParse(prop, b) Then Return "Convert.ToBoolean"        
        Return ""
    End Function

    Public Shared Function GetPropertyType(ByVal prop as String) as String
        If IsNumeric(prop) Then Return "int"
        If IsDate(prop) Then Return "DateTime"
        dim b as Boolean
        If Boolean.TryParse(prop, b) Then Return "bool"
        Return "string"
    End Function

#>

他のヒント

これは、事前にビルドステップで行うことができます。これはかなり簡単に行うことができます - クラスを再生するプログラムまたはスクリプトまたはテンプレートを書いて、ビルド前のイベントでそれを呼び出すだけですが、これにより、クラスが得られるまで、新しいメンバーに赤いウィグリーとインテリセンスが得られません再生。

少しマニュアルですが、おそらくより便利なアプローチは、 T4テンプレート それをあなたのプロジェクトに含めてください。ただし、新しい設定を追加するたびにテンプレートを再変換することを忘れないでください。これはあまりにも面倒でしょうか?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top