سؤال

ما أريد تحقيقه هو بسيط جدا:لدي نماذج Windows (.NET framework 3.5) تطبيق يستخدم مسار قراءة المعلومات.هذا المسار يمكن تعديلها من قبل المستخدم باستخدام خيارات شكل أقدمها.

الآن, أريد أن حفظ قيمة path إلى ملف لاستخدامها في وقت لاحق.هذا من شأنه أن يكون واحدا من العديد من الإعدادات المحفوظة في هذا الملف.هذا الملف الجلوس مباشرة في مجلد التطبيق.

أنا أفهم أن هناك ثلاثة خيارات متاحة:

  • إعدادات تكوين الملف (appname.exe.التكوين)
  • التسجيل
  • مخصص ملف XML

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

هل هذا يعني أنني يجب أن تستخدم مخصص ملف XML إلى حفظ إعدادات التكوين?إذا كنت تود أن ترى رمز مثال على ذلك (C#).

لقد رأيت مناقشات أخرى حول هذا الموضوع, ولكن لا يزال من غير الواضح بالنسبة لي.

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

المحلول

إذا كنت تعمل باستخدام Visual Studio، فمن السهل جدًا الحصول على إعدادات ثابتة.انقر بزر الماوس الأيمن على المشروع في Solution Explorer، واختر خصائص.حدد علامة التبويب "الإعدادات"، وانقر فوق الارتباط التشعبي في حالة عدم وجود الإعدادات.استخدم علامة التبويب "الإعدادات" لإنشاء إعدادات التطبيق.يقوم Visual Studio بإنشاء الملفات Settings.settings و Settings.Designer.settings التي تحتوي على فئة المفردة Settings موروث من قاعدة إعدادات التطبيق.يمكنك الوصول إلى هذا الفصل من التعليمات البرمجية الخاصة بك لقراءة/كتابة إعدادات التطبيق:

Properties.Settings.Default["SomeProperty"] = "Some Value";
Properties.Settings.Default.Save(); // Saves settings in application configuration file

تنطبق هذه التقنية على وحدة التحكم ونماذج Windows وأنواع المشاريع الأخرى.

لاحظ أنك بحاجة إلى ضبط نِطَاق خاصية الإعدادات الخاصة بك.إذا حددت نطاق التطبيق، فستكون الإعدادات الافتراضية <خاصيتك> للقراءة فقط.

نصائح أخرى

إذا كنت تخطط للحفظ في ملف داخل نفس الدليل الذي يحتوي على ملفك القابل للتنفيذ، فإليك حل جيد يستخدم JSON شكل:

using System;
using System.IO;
using System.Web.Script.Serialization;

namespace MiscConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            MySettings settings = MySettings.Load();
            Console.WriteLine("Current value of 'myInteger': " + settings.myInteger);
            Console.WriteLine("Incrementing 'myInteger'...");
            settings.myInteger++;
            Console.WriteLine("Saving settings...");
            settings.Save();
            Console.WriteLine("Done.");
            Console.ReadKey();
        }

        class MySettings : AppSettings<MySettings>
        {
            public string myString = "Hello World";
            public int myInteger = 1;
        }
    }

    public class AppSettings<T> where T : new()
    {
        private const string DEFAULT_FILENAME = "settings.json";

        public void Save(string fileName = DEFAULT_FILENAME)
        {
            File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(this));
        }

        public static void Save(T pSettings, string fileName = DEFAULT_FILENAME)
        {
            File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(pSettings));
        }

        public static T Load(string fileName = DEFAULT_FILENAME)
        {
            T t = new T();
            if(File.Exists(fileName))
                t = (new JavaScriptSerializer()).Deserialize<T>(File.ReadAllText(fileName));
            return t;
        }
    }
}

التسجيل أمر محظور.لست متأكدًا مما إذا كان المستخدم الذي يستخدم تطبيقك لديه الحقوق الكافية للكتابة إلى السجل.

يمكنك استخدام ال app.config ملف لحفظ الإعدادات على مستوى التطبيق (التي هي نفسها لكل مستخدم يستخدم التطبيق الخاص بك).

سأقوم بتخزين الإعدادات الخاصة بالمستخدم في ملف XML، والذي سيتم حفظه فيه تخزين معزول أو في SpecialFolder.ApplicationData الدليل.

بجانب ذلك، بدءًا من .NET 2.0، من الممكن تخزين القيم مرة أخرى في ملف app.config ملف.

ال ApplicationSettings لا تدعم الفئة حفظ الإعدادات في ملف app.config.يرجع هذا إلى حد كبير إلى التصميم، فالتطبيقات التي تعمل باستخدام حساب مستخدم مؤمن بشكل صحيح (مثل Vista UAC) لا تتمتع بإمكانية الوصول للكتابة إلى مجلد تثبيت البرنامج.

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

لا تزال وسيطة التسجيل/configurationSettings/XML نشطة للغاية.لقد استخدمتها جميعًا، مع تقدم التكنولوجيا، لكن مفضلتي تعتمد عليها نظام ثريد مدموج مع تخزين معزول.

يسمح النموذج التالي بتخزين كائنات تسمى خصائص لملف في مخزن معزول.مثل:

AppSettings.Save(myobject, "Prop1,Prop2", "myFile.jsn");

يمكن استرداد الخصائص باستخدام:

AppSettings.Load(myobject, "myFile.jsn");

إنها مجرد عينة، ولا تشير إلى أفضل الممارسات.

internal static class AppSettings
{
    internal static void Save(object src, string targ, string fileName)
    {
        Dictionary<string, object> items = new Dictionary<string, object>();
        Type type = src.GetType();

        string[] paramList = targ.Split(new char[] { ',' });
        foreach (string paramName in paramList)
            items.Add(paramName, type.GetProperty(paramName.Trim()).GetValue(src, null));

        try
        {
            // GetUserStoreForApplication doesn't work - can't identify.
            // application unless published by ClickOnce or Silverlight
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForAssembly();
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Create, storage))
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.Write((new JavaScriptSerializer()).Serialize(items));
            }

        }
        catch (Exception) { }   // If fails - just don't use preferences
    }

    internal static void Load(object tar, string fileName)
    {
        Dictionary<string, object> items = new Dictionary<string, object>();
        Type type = tar.GetType();

        try
        {
            // GetUserStoreForApplication doesn't work - can't identify
            // application unless published by ClickOnce or Silverlight
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForAssembly();
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Open, storage))
            using (StreamReader reader = new StreamReader(stream))
            {
                items = (new JavaScriptSerializer()).Deserialize<Dictionary<string, object>>(reader.ReadToEnd());
            }
        }
        catch (Exception) { return; }   // If fails - just don't use preferences.

        foreach (KeyValuePair<string, object> obj in items)
        {
            try
            {
                tar.GetType().GetProperty(obj.Key).SetValue(tar, obj.Value, null);
            }
            catch (Exception) { }
        }
    }
}

أردت أن حصة مكتبة لقد بنيت هذا.انها صغيرة المكتبة ، ولكن تحسن كبير (IMHO) انتهى .ملفات الإعدادات.

المكتبة يسمى ذرة (جيثب), هنا هو قديم رمز المشروع المادة لقد كتبت عن ذلك.

هنا هو كيف يمكنك استخدامها لتتبع نافذة في الحجم والموقع:

public MainWindow()
{
    InitializeComponent();

    _stateTracker.Configure(this)
        .IdentifyAs("MyMainWindow")
        .AddProperties(nameof(Height), nameof(Width), nameof(Left), nameof(Top), nameof(WindowState))
        .RegisterPersistTrigger(nameof(Closed))
        .Apply();
}

فائدة مقارنة .ملفات الإعدادات: هناك أقل بكثير رمز, و هناك الكثير أقل عرضة للخطأ حيث تحتاج فقط أن أذكر كل الممتلكات مرة واحدة.

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

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

هو شكلي للغاية ، يمكنك تكوين:- عندما تكون البيانات استمرت وتطبيقها على الصعيد العالمي أو تتبع كل كائن - كيف تسلسل - حيث يتم تخزينها (مثلملف قاعدة بيانات على الانترنت التخزين المعزول التسجيل) - القواعد التي يمكن أن إلغاء تطبيق/استمرار بيانات عقار

ثق بي, المكتبة من الدرجة الأولى!

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

فيما يلي مثال لتخزين موضع النموذج وحجمه.

كائن بيانات التكوين مكتوب بقوة وسهل الاستخدام:

[Serializable()]
public class CConfigDO
{
    private System.Drawing.Point m_oStartPos;
    private System.Drawing.Size m_oStartSize;

    public System.Drawing.Point StartPos
    {
        get { return m_oStartPos; }
        set { m_oStartPos = value; }
    }

    public System.Drawing.Size StartSize
    {
        get { return m_oStartSize; }
        set { m_oStartSize = value; }
    }
}

فئة مدير للحفظ والتحميل:

public class CConfigMng
{
    private string m_sConfigFileName = System.IO.Path.GetFileNameWithoutExtension(System.Windows.Forms.Application.ExecutablePath) + ".xml";
    private CConfigDO m_oConfig = new CConfigDO();

    public CConfigDO Config
    {
        get { return m_oConfig; }
        set { m_oConfig = value; }
    }

    // Load configuration file
    public void LoadConfig()
    {
        if (System.IO.File.Exists(m_sConfigFileName))
        {
            System.IO.StreamReader srReader = System.IO.File.OpenText(m_sConfigFileName);
            Type tType = m_oConfig.GetType();
            System.Xml.Serialization.XmlSerializer xsSerializer = new System.Xml.Serialization.XmlSerializer(tType);
            object oData = xsSerializer.Deserialize(srReader);
            m_oConfig = (CConfigDO)oData;
            srReader.Close();
        }
    }

    // Save configuration file
    public void SaveConfig()
    {
        System.IO.StreamWriter swWriter = System.IO.File.CreateText(m_sConfigFileName);
        Type tType = m_oConfig.GetType();
        if (tType.IsSerializable)
        {
            System.Xml.Serialization.XmlSerializer xsSerializer = new System.Xml.Serialization.XmlSerializer(tType);
            xsSerializer.Serialize(swWriter, m_oConfig);
            swWriter.Close();
        }
    }
}

يمكنك الآن إنشاء مثيل واستخدامه في أحداث تحميل وإغلاق النموذج الخاص بك:

    private CConfigMng oConfigMng = new CConfigMng();

    private void Form1_Load(object sender, EventArgs e)
    {
        // Load configuration
        oConfigMng.LoadConfig();
        if (oConfigMng.Config.StartPos.X != 0 || oConfigMng.Config.StartPos.Y != 0)
        {
            Location = oConfigMng.Config.StartPos;
            Size = oConfigMng.Config.StartSize;
        }
    }

    private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
        // Save configuration
        oConfigMng.Config.StartPos = Location;
        oConfigMng.Config.StartSize = Size;
        oConfigMng.SaveConfig();
    }

وملف XML المُنتج قابل للقراءة أيضًا:

<?xml version="1.0" encoding="utf-8"?>
<CConfigDO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <StartPos>
    <X>70</X>
    <Y>278</Y>
  </StartPos>
  <StartSize>
    <Width>253</Width>
    <Height>229</Height>
  </StartSize>
</CConfigDO>

لا أحب الحل المقترح للاستخدام web.config أو app.config.حاول قراءة ملف XML الخاص بك.القي نظرة على ملفات إعدادات XML - لا مزيد من web.config.

الخيارات الأخرى, بدلا من استخدام مخصص ملف XML يمكننا استخدام المستخدم أكثر ودية تنسيق الملف:JSON أو YAML الملف.

  • إذا كنت تستخدم .NET 4.0 ديناميكية هذه المكتبة هو حقا سهلة الاستخدام (تسلسل, تسلسل, الكائنات المتداخلة الدعم و طلب الإخراج كما يحلو لك + دمج عدة إعدادات واحدة) JsonConfig (استخدام ما يعادل ApplicationSettingsBase)
  • ل .صافي YAML تكوين مكتبة...لم أجد واحد هو أن سهلة الاستخدام كما JsonConfig

يمكنك تخزين ملف الإعدادات في العديد من المجلدات الخاصة (لجميع المستخدمين لكل مستخدم) كما هو موضح هنا البيئة.SpecialFolder التعداد و ملفات متعددة (الافتراضي للقراءة فقط في دور لكل مستخدم ، إلخ.)

إذا اخترت استخدام إعدادات متعددة, يمكنك دمج هذه الإعدادات:على سبيل المثال, دمج الإعدادات الافتراضية + BasicUser + AdminUser.يمكنك استخدام القواعد الخاصة بك:آخر واحد يتجاوز قيمة ، وما إلى ذلك.

"هل هذا يعني أنني يجب أن تستخدم مخصص ملف XML إلى حفظ إعدادات التكوين?" لا ليس بالضرورة.نحن نستخدم SharpConfig لمثل هذه العمليات.

فعلى سبيل المثال ، إذا config مثل هذا

[General]
# a comment
SomeString = Hello World!
SomeInteger = 10 # an inline comment

يمكننا استرداد قيم مثل هذا

var config = Configuration.LoadFromFile("sample.cfg");
var section = config["General"];

string someString = section["SomeString"].StringValue;
int someInteger = section["SomeInteger"].IntValue;

وهو متوافق مع .Net 2.0 و أعلى.يمكننا إنشاء ملفات التكوين على الطاير ونحن يمكن حفظه في وقت لاحق.المصدر: http://sharpconfig.net/ جيثب: https://github.com/cemdervis/SharpConfig

وآمل أن يساعد.

بقدر ما أستطيع أن أقول، يدعم .NET الإعدادات المستمرة باستخدام أداة إعدادات التطبيق المضمنة:

تعمل ميزة إعدادات التطبيق في Windows Forms على تسهيل إنشاء التطبيقات المخصصة وتفضيلات المستخدم وتخزينها والحفاظ عليها على جهاز الكمبيوتر العميل.باستخدام إعدادات تطبيق Windows Forms، لا يمكنك تخزين بيانات التطبيق مثل سلاسل اتصال قاعدة البيانات فحسب، بل يمكنك أيضًا تخزين البيانات الخاصة بالمستخدم، مثل تفضيلات تطبيق المستخدم.باستخدام Visual Studio أو التعليمات البرمجية المُدارة المخصصة، يمكنك إنشاء إعدادات جديدة وقراءتها وكتابتها على القرص وربطها بالخصائص الموجودة في النماذج الخاصة بك والتحقق من صحة بيانات الإعدادات قبل التحميل والحفظ.- http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx

في بعض الأحيان تريد التخلص من تلك الإعدادات المحفوظة في ملف web.config أو app.config التقليدي.تريد مزيدًا من التحكم الدقيق في نشر إدخالات الإعدادات وتصميم البيانات المنفصلة.أو الشرط هو تمكين إضافة إدخالات جديدة في وقت التشغيل.

أستطيع أن أتخيل خيارين جيدين:

  • النسخة المكتوبة بقوة و
  • النسخة الموجهة للكائنات.

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

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

يمكنك العثور على التعليمات البرمجية لكلا التطبيقين اللذين يعملان بكامل طاقتهما هنا.

public static class SettingsExtensions
{
    public static bool TryGetValue<T>(this Settings settings, string key, out T value)
    {
        if (settings.Properties[key] != null)
        {
            value = (T) settings[key];
            return true;
        }

        value = default(T);
        return false;
    }

    public static bool ContainsKey(this Settings settings, string key)
    {
        return settings.Properties[key] != null;
    }

    public static void SetValue<T>(this Settings settings, string key, T value)
    {
        if (settings.Properties[key] == null)
        {
            var p = new SettingsProperty(key)
            {
                PropertyType = typeof(T),
                Provider = settings.Providers["LocalFileSettingsProvider"],
                SerializeAs = SettingsSerializeAs.Xml
            };
            p.Attributes.Add(typeof(UserScopedSettingAttribute), new UserScopedSettingAttribute());
            var v = new SettingsPropertyValue(p);
            settings.Properties.Add(p);
            settings.Reload();
        }
        settings[key] = value;
        settings.Save();
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top