سؤال

هذا هو السؤال أولاً:

هل هذا ممكن؟ أنا أستلهم من عمل جو ووبيل (Redux من المنسي مشروع CodePlex). هنا ، تقوم بعملك على إنشاء ملف التعريف الخاص بك للمزود ، ويقوم بعمل الأسطورة لإنشاء الكتابة القوية له ، وإنشاء واجهة فعالة لفئة الملف الشخصي.

والآن القصة الخلفية!

أنا حقا لا أحب السلاسل السحرية. إنها سيئة للغاية ويمكن أن تسبب بعض المشكلات الخطيرة عندما يتعلق الأمر بتحديث التطبيق الخاص بك. بعد أن عملت بلغات مثل PHP و Coldfusion ، أعرف أنه من السهل وضعها في طلبك ونسيانها حتى تحتاج إلى تغيير واحدة. ثم عليك أن تصطاد كل اختلاف منها وتغييرها وفقًا لذلك.

.NET في الحقيقة ليس أفضل بكثير إذا اتبعت قوالب تطبيق "Out Out the Box". تستخدم الكثير من الأمثلة الموجودة هناك في web.config لتخزين الإعدادات المختلفة. إنه بالفعل مكان جيد للتخزين ، وهو مثالي لمعظم التطبيقات. ومع ذلك ، تبدأ المشكلات في الظهور ، عند البدء في الاتصال بها مباشرة - على سبيل المثال ConfigurationManager.AppSettings["MyAppSetting"]. بعد ذلك ، فأنت لست أفضل حالًا من مستخدم PHP حيث تعود إلى استخدام الأوتار السحرية.

هذا هو المكان واجهات تعال. توفر الواجهات طريقة لإنشاء كائن قوي من النوع من سلسلة سحرية في مكان واحد ، وإشارة المطور إلى ذلك من بقية التطبيق.

الآن ، بدلاً من استخدام web.config لاحتواء أجهزة التطبيقات الخاصة بي ، أستخدم قاعدة بيانات للاحتفاظ بها جميعًا. عند بدء التطبيق ، يتم استرداد مجموعات الاسم/القيمة ، ثم يتم إضافتها بالتتابع إلى ConfigurationManager.AppSettings عبر Set. لا بيجي (بصرف النظر عن مشكلة كان لدي في وقت سابق!).

يمكن الوصول إلى "واجهة التطبيق هذه" من خلال طبقة البيانات الخاصة بي وطبقة الخدمة وطبقة العرض التقديمي وتحمل أشياء مثل وضع التطبيق ، والتي يتم استخدام نقطة الخدمة لاستخدام Yada Yada وتحد من الحاجة إلى البحث عن العديد من الأوتار السحرية ، وصولاً إلى سحرين سلاسل - واحدة (الاسم) في الواجهة ، والآخر (الاسم والقيمة) في نقطة الخلق (والتي ، بالنسبة لي هي DB).

سوف تصبح فئة الواجهة هذه في نهاية المطاف كبيرة جدًا وسأتعب في النهاية من الاضطرار إلى تحديث كل منهما.

لذا فإن ما أود القيام به هو الحصول على فئة ApplicationFacade التي تتمثل في تلقائي في كل مرة يتم فيها الإنشاء. والآن عد إلى البداية ... هل هذا ممكن؟

هل كانت مفيدة؟

المحلول

يمكنك أيضًا استخدام قوالب CODESMITH لهذا الغرض. الميزة هي أنه يمكنك تعيين خصائص ملفات القالب ليتم تجديدها على كل بناء (Set BuildAction = "coxt")

تحريركما بحثت عن مثل هذا الحل. بعد googling ، وجدت قالب T4 الأساسي لإنشاء مثل هذا الفصل. لقد أعيد تصميمه ويمكنك العثور عليه أدناه.

القالب ينشئ فئة Wrapper لقسم مجموعة التطبيقات من ملف الويب الخاص بك. config/app.config

افترض أن لديك أسطرًا التالية للإعدادات في ملف التكوين

  <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

#>

نصائح أخرى

يمكنك القيام بذلك بخطوة ما قبل البناء. من السهل القيام بذلك بشكل معقول-ما عليك سوى كتابة برنامج أو نص أو قالب يجدد الفصل ، ويسميه في حدث ما قبل البناء-ولكن هذا سيمنحك Wigglies Red ولا يوجد intellisense على أي أعضاء جدد حتى يحصل الفصل على الفصل مجدد.

سيكون النهج الأكثر يدويًا ، ولكن ربما يكون أكثر ملاءمة هو إنشاء ملف قالب T4 وتضمين ذلك في مشروعك. ومع ذلك ، ستحتاج إلى تذكر إعادة تحويل القالب في كل مرة تضيف فيها إعدادًا جديدًا. هل سيكون هذا مرهقًا جدًا؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top