سؤال

هل من الممكن أن تفعل شيئا مثل التالية في app.config أو web.config الملفات ؟

<appSettings>
 <add key="MyBaseDir" value="C:\MyBase" />
 <add key="Dir1" value="[MyBaseDir]\Dir1"/>
 <add key="Dir2" value="[MyBaseDir]\Dir2"/>
</appSettings>

ثم تريد الوصول إلى Dir2 في قانون بلدي ببساطة قائلا:

 ConfigurationManager.AppSettings["Dir2"]

وهذا سوف يساعد لي عندما أقوم بتثبيت التطبيق في ملقمات مختلفة و مواقع حيث سوف تضطر إلى تغيير إدخال واحد في حياتي app.config.(وأنا أعلم أنني يمكن إدارة جميع سلسلة في المدونة, ولكن أنا أفضل هذه الطريقة).

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

المحلول

وسؤال جيد.

وأنا لا أعتقد أن هناك. أعتقد أنه من المعروف جيدا إذا كان هناك طريقة سهلة، وأنا أرى أن مايكروسوفت إنشاء آلية في Visual Studio 2010 لنشر ملفات التكوين مختلفة لنشر والاختبار.

وقال مع ذلك، ولكن؛ لقد وجدت أن كنت في قسم ConnectionStrings يكون لدينا نوع من النائب يسمى "| DataDirectory |". ربما يمكن أن يكون لديك نظرة على ما هو في العمل هناك ...

وهنا قطعة من machine.config تبين ما يلي:

 <connectionStrings>
    <add
        name="LocalSqlServer"
        connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
        providerName="System.Data.SqlClient"
    />
 </connectionStrings>

نصائح أخرى

وA قليلا أكثر تعقيدا، ولكن حتى أكثر مرونة، والبديل هو إنشاء فئة التي تمثل القسم التكوين. في ملف / app.config web.config الخاص بك، هل يمكن أن يكون هذا:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <!-- This section must be the first section within the <configuration> node -->
    <configSections>
        <section name="DirectoryInfo" type="MyProjectNamespace.DirectoryInfoConfigSection, MyProjectAssemblyName" />
    </configSections>

    <DirectoryInfo>
        <Directory MyBaseDir="C:\MyBase" Dir1="Dir1" Dir2="Dir2" />
    </DirectoryInfo>
</configuration>

وبعد ذلك، في التعليمات البرمجية. NET الخاص بك (سوف تستخدم C # في بلدي على سبيل المثال)، يمكنك إنشاء فئتين من هذا القبيل:

using System;
using System.Configuration;

namespace MyProjectNamespace {

    public class DirectoryInfoConfigSection : ConfigurationSection {

        [ConfigurationProperty("Directory")]
        public DirectoryConfigElement Directory {
            get {
                return (DirectoryConfigElement)base["Directory"];
            }
    }

    public class DirectoryConfigElement : ConfigurationElement {

        [ConfigurationProperty("MyBaseDir")]
        public String BaseDirectory {
            get {
                return (String)base["MyBaseDir"];
            }
        }

        [ConfigurationProperty("Dir1")]
        public String Directory1 {
            get {
                return (String)base["Dir1"];
            }
        }

        [ConfigurationProperty("Dir2")]
        public String Directory2 {
            get {
                return (String)base["Dir2"];
            }
        }
        // You can make custom properties to combine your directory names.
        public String Directory1Resolved {
            get {
                return System.IO.Path.Combine(BaseDirectory, Directory1);
            }
        }
    }
}

وأخيرا، في التعليمات البرمجية البرنامج الخاص بك، يمكنك الوصول إلى المتغيرات app.config، وذلك باستخدام الطبقات الجديدة، بهذه الطريقة:

DirectoryInfoConfigSection config =
  (DirectoryInfoConfigSection)ConfigurationManager.GetSection("DirectoryInfo");
String dir1Path = config.Directory.Directory1Resolved;  // This value will equal "C:\MyBase\Dir1"

ويمكنك القيام بها باستخدام مكتبتي توسعية: http://nuget.org/List/Packages/Expansive مصدر متاح هنا: https://github.com/anderly/Expansive

رأيت هذا السؤال.

باختصار, لا يوجد متغير الاستيفاء في تكوين التطبيق.

لديك خياران

  1. يمكنك لفة الخاص بك إلى استبدال المتغيرات في وقت التشغيل
  2. في وقت البناء, تدليك تكوين التطبيق خاص تفاصيل الهدف نشر البيئة.بعض التفاصيل عن هذا في التعامل مع التكوين-كابوس

لديك عدة خيارات. هل يمكن أن تفعل هذا مع خطوة / نشر بناء التي من شأنها معالجة ملف التكوين الخاص بك استبدال المتغيرات الخاصة بك مع القيمة الصحيحة.

وثمة خيار آخر يتمثل في تحديد المقطع تكوين الخاصة بك التي دعمت هذا. على سبيل المثال تخيل هذا XML:

<variableAppSettings>
 <variables>
    <add key="@BaseDir" value="c:\Programs\Widget"/>
 </variables>
 <appSettings>
    <add key="PathToDir" value="@BaseDir\Dir1"/>
 </appSettings>
</variableAppSettings>

والآن هل تنفيذ هذه باستخدام كائنات تكوين مخصص التي من شأنها أن التعامل مع استبدال المتغيرات بالنسبة لك في وقت التشغيل.

وUsally، وأنا في نهاية المطاف كتابة فئة ثابتة مع خصائص للوصول إلى كل من إعدادات بلدي الملف web.config.

public static class ConfigManager 
{
    public static string MyBaseDir
    {
        return ConfigurationManager.AppSettings["MyBaseDir"].toString();
    }

    public static string Dir1
    {
        return MyBaseDir + ConfigurationManager.AppSettings["Dir1"].toString();
    }

}

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

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

ويمكنك استخدام متغيرات البيئة في app.config الخاصة بك لهذا السيناريو أن تصف

<configuration>
  <appSettings>
    <add key="Dir1" value="%MyBaseDir%\Dir1"/>
  </appSettings>
</configuration>

وبعد ذلك يمكنك بسهولة الحصول على المسار مع:

var pathFromConfig = ConfigurationManager.AppSettings["Dir1"];
var expandedPath = Environment.ExpandEnvironmentVariables(pathFromConfig);

وداخل <appSettings> يمكنك إنشاء مفاتيح التطبيق،

<add key="KeyName" value="Keyvalue"/>

وفي وقت لاحق يمكنك الوصول إلى هذه القيم باستخدام:

ConfigurationManager.AppSettings["Keyname"]

وأود أن أقترح عليك DslConfig . مع DslConfig يمكنك استخدام ملفات التكوين الهرمي من التكوين العالمية، التكوين في الخادم المضيف إلى التكوين في التطبيق على كل الخادم المضيف (انظر AppSpike).
إذا كان هذا هو معقد بالنسبة لك يمكنك فقط استخدام التكوين العالمي Variables.var
مجرد تكوين في Varibales.var

baseDir = "C:\MyBase"
Var["MyBaseDir"] = baseDir
Var["Dir1"] = baseDir + "\Dir1"
Var["Dir2"] = baseDir + "\Dir2"

والحصول على قيم التكوين مع

Configuration config = new DslConfig.BooDslConfiguration()
config.GetVariable<string>("MyBaseDir")
config.GetVariable<string>("Dir1")
config.GetVariable<string>("Dir2")

وأنا لا أعتقد أنك يمكن أن تعلن واستخدام المتغيرات لتحديد appSettings مفاتيح داخل ملف التكوين. لقد تمكنت دائما تسلسالت في التعليمات البرمجية مثلك.

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

<appSettings file="..\OverrideSettings.config">

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

وأوصي التالية حل مات Hamsmith ل. إذا كانت قضية لتنفيذ، ثم لماذا لا ننشئ طريقة التمديد التي تطبق هذا في الخلفية على الطبقة AppSettings؟

وشيء من هذا القبيل:

    public static string GetValue(this NameValueCollection settings, string key)
    {

    }

وداخل الأسلوب الذي بحث من خلال DictionaryInfoConfigSection باستخدام ينق وإرجاع القيمة مع مفتاح التصفح. سوف تحتاج إلى تحديث ملف التكوين الرغم من ذلك، إلى شيء على طول هذه الخطوط:

<appSettings>
  <DirectoryMappings>
    <DirectoryMap key="MyBaseDir" value="C:\MyBase" />
    <DirectoryMap key="Dir1" value="[MyBaseDir]\Dir1"/>
    <DirectoryMap key="Dir2" value="[MyBaseDir]\Dir2"/>
  </DirectoryMappings>
</appSettings>

لقد جاء مع هذا الحل:

  1. في إعدادات التطبيق.إعدادات تعريف متغير ConfigurationBase (مع نوع=سلسلة نطاق=التطبيق)
  2. لقد قدم متغير في سمات الهدف في الإعدادات.إعدادات كل تلك الصفات قد لتعيين نطاق=المستخدم
  3. في التطبيق.xaml.cs قرأت من القيمة إذا كان ConfigurationBase
  4. في التطبيق.xaml.cs استبدلت جميع المتغيرات مع ConfigurationBase القيمة.من أجل استبدال القيم في وقت التشغيل سمات بد من تعيين Scopr=المستخدم

أنا سعيد حقا مع هذا الحل لأنه يجب أن تغير كل الصفات يدويا إذا قمت بإضافة واحد جديد يجب أن الصدد هذا في التطبيق.xaml.cs.

هنا مقتطف من التطبيق.xaml.cs:

string configBase = Settings.Default.ConfigurationBase;
Settings.Default.CommonOutput_Directory = Settings.Default.CommonOutput_Directory.Replace("${ConfigurationBase}", configBase);

التحديث

فقط وجدت تحسنا (مرة أخرى مدونة مقتطف من التطبيق.xaml.cs):

string configBase = Settings.Default.ConfigurationBase;

foreach (SettingsProperty settingsProperty in Settings.Default.Properties)
{
    if (!settingsProperty.IsReadOnly && settings.Default[settingsProperty.Name] is string)
    {
        Settings.Default[settingsProperty.Name] = ((string)Settings.Default[settingsProperty.Name]).Replace("${ConfigurationBase}", configBase);
    }
}

الآن بدائل العمل لجميع الصفات في الإعدادات التي Type=سلسلة نطاق=المستخدم.أعتقد أنني أحب ذلك بهذه الطريقة.

UPDATE2

على ما يبدو تحديد نطاق=التطبيق غير مطلوب عند تشغيل فوق خصائص.

ثلاثة حلول ممكنة

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

على سبيل المثال لقد استخدمت بعد إعداد التطبيق في تطبيق وحدة التحكم:

<appSettings>
    <add key="EnvironmentVariableExample" value="%BaseDir%\bin"/>
    <add key="StaticClassExample" value="bin"/>
    <add key="InterpollationExample" value="{0}bin"/>
  </appSettings>

1.استخدام متغيرات البيئة

أعتقد autocro autocro الجواب لمست على ذلك.أنا فقط أقوم تنفيذ هذا ينبغي أن يكون كافيا عند بناء أو التصحيح دون الحاجة إلى إغلاق visual studio.لقد استخدمت هذا الحل مرة في اليوم...

  • إنشاء pre-build التي سوف تستخدم MSBuild المتغيرات

    تحذير:استخدام متغير أنه لن يتم استبدالها بسهولة وذلك باستخدام اسم المشروع أو شيء مماثل مثل اسم متغير.

    SETX BaseDir "$(ProjectDir)"

  • إعادة تعيين المتغيرات ؛ استخدام شيء من هذا القبيل ما يلي:

    تحديث متغيرات البيئة على تجاوز سعة مكدس

  • استخدام الإعداد في التعليمات البرمجية:

'

private void Test_Environment_Variables()
{
    string BaseDir = ConfigurationManager.AppSettings["EnvironmentVariableExample"];
    string ExpandedPath = Environment.ExpandEnvironmentVariables(BaseDir).Replace("\"", ""); //The function addes a " at the end of the variable
    Console.WriteLine($"From within the C# Console Application {ExpandedPath}");
}

'

2.استخدام سلسلة الاستيفاء:

  • استخدام سلسلة.شكل() وظيفة

`

private void Test_Interpollation()
{
    string ConfigPath = ConfigurationManager.AppSettings["InterpollationExample"];
    string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\"));
    string ExpandedPath = string.Format(ConfigPath, SolutionPath.ToString());
    Console.WriteLine($"Using old interpollation {ExpandedPath}");
}

`

3.باستخدام فئة ثابتة, هذا هو الحل أنا في الغالب استخدام.

  • تنفيذ

`

private void Test_Static_Class()
{
    Console.WriteLine($"Using a static config class {Configuration.BinPath}");
}

`

  • ثابت الدرجة

`

static class Configuration
{
    public static string BinPath
    {
        get
        {
            string ConfigPath = ConfigurationManager.AppSettings["StaticClassExample"];
            string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\"));
            return SolutionPath + ConfigPath;
        }
    }
}

`

رمز المشروع:

التطبيق.التكوين:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
  <appSettings>
    <add key="EnvironmentVariableExample" value="%BaseDir%\bin"/>
    <add key="StaticClassExample" value="bin"/>
    <add key="InterpollationExample" value="{0}bin"/>
  </appSettings>
</configuration>

البرنامج.cs

using System;
using System.Configuration;
using System.IO;

namespace ConfigInterpollation
{
    class Program
    {
        static void Main(string[] args)
        {
            new Console_Tests().Run_Tests();
            Console.WriteLine("Press enter to exit");
            Console.ReadLine();
        }        
    }

    internal class Console_Tests
    {
        public void Run_Tests()
        {
            Test_Environment_Variables();
            Test_Interpollation();
            Test_Static_Class();
        }
        private void Test_Environment_Variables()
        {
            string ConfigPath = ConfigurationManager.AppSettings["EnvironmentVariableExample"];
            string ExpandedPath = Environment.ExpandEnvironmentVariables(ConfigPath).Replace("\"", "");
            Console.WriteLine($"Using environment variables {ExpandedPath}");
        }

        private void Test_Interpollation()
        {
            string ConfigPath = ConfigurationManager.AppSettings["InterpollationExample"];
            string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\"));
            string ExpandedPath = string.Format(ConfigPath, SolutionPath.ToString());
            Console.WriteLine($"Using interpollation {ExpandedPath}");
        }

        private void Test_Static_Class()
        {
            Console.WriteLine($"Using a static config class {Configuration.BinPath}");
        }
    }

    static class Configuration
    {
        public static string BinPath
        {
            get
            {
                string ConfigPath = ConfigurationManager.AppSettings["StaticClassExample"];
                string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\"));
                return SolutionPath + ConfigPath;
            }
        }
    }
}

قبل بناء الحدث:

المشروع إعدادات -> بناء الأحداث

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