มีเทียบเท่ากับapp.config
สำหรับไลบรารี (DLLs) หรือไม่ ถ้าไม่เป็นวิธีที่ง่ายที่สุดในการจัดเก็บการตั้งค่าที่เฉพาะเจาะจงกับห้องสมุดคืออะไร? โปรดพิจารณาว่าอาจใช้ไลบรารีในแอปพลิเคชันอื่น
มีเทียบเท่ากับapp.config
สำหรับไลบรารี (DLLs) หรือไม่ ถ้าไม่เป็นวิธีที่ง่ายที่สุดในการจัดเก็บการตั้งค่าที่เฉพาะเจาะจงกับห้องสมุดคืออะไร? โปรดพิจารณาว่าอาจใช้ไลบรารีในแอปพลิเคชันอื่น
คำตอบ:
คุณสามารถมีไฟล์การกำหนดค่าแยกต่างหาก แต่คุณจะต้องอ่านด้วยตนเอง "ด้วยตนเอง" ConfigurationManager.AppSettings["key"]
จะอ่านเฉพาะการกำหนดค่าของแอสเซมบลีที่กำลังทำงานอยู่
สมมติว่าคุณกำลังใช้ Visual Studio เป็น IDE ของคุณคุณสามารถคลิกขวาที่โครงการที่ต้องการ→เพิ่ม→รายการใหม่→ไฟล์การกำหนดค่าแอปพลิเคชัน
สิ่งนี้จะเพิ่มApp.config
ไปยังโฟลเดอร์โครงการใส่การตั้งค่าของคุณใน<appSettings>
ส่วนใต้ ในกรณีที่คุณไม่ได้ใช้ Visual Studio และเพิ่มไฟล์ด้วยตนเองตรวจสอบให้แน่ใจว่าได้ตั้งชื่อดังกล่าว: DllName.dll.configมิฉะนั้นรหัสด้านล่างจะทำงานไม่ถูกต้อง
ตอนนี้อ่านจากไฟล์นี้มีฟังก์ชั่นดังกล่าว:
string GetAppSetting(Configuration config, string key)
{
KeyValueConfigurationElement element = config.AppSettings.Settings[key];
if (element != null)
{
string value = element.Value;
if (!string.IsNullOrEmpty(value))
return value;
}
return string.Empty;
}
และใช้มัน:
Configuration config = null;
string exeConfigPath = this.GetType().Assembly.Location;
try
{
config = ConfigurationManager.OpenExeConfiguration(exeConfigPath);
}
catch (Exception ex)
{
//handle errror here.. means DLL has no sattelite configuration file.
}
if (config != null)
{
string myValue = GetAppSetting(config, "myKey");
...
}
คุณจะต้องเพิ่มการอ้างอิงไปยัง System.Configuration namespace เพื่อให้คลาส ConfigurationManager พร้อมใช้งาน
เมื่อสร้างโครงการนอกเหนือจาก DLL คุณจะมีDllName.dll.config
ไฟล์ด้วยนั่นคือไฟล์ที่คุณต้องเผยแพร่ด้วย DLL เอง
ข้างต้นเป็นรหัสตัวอย่างพื้นฐานสำหรับผู้ที่สนใจในตัวอย่างเต็มรูปแบบโปรดดูคำตอบอื่น ๆนี้
น่าเสียดายที่คุณสามารถมีไฟล์ app.config ได้เพียงไฟล์เดียวต่อการดำเนินการดังนั้นหากคุณมี DLL ที่เชื่อมโยงกับแอปพลิเคชันของคุณพวกเขาจะไม่สามารถมีไฟล์ app.config ของตัวเองได้
วิธีแก้ไขคือ:
คุณไม่จำเป็นต้องวางไฟล์ App.config ในโครงการของ Class Library
คุณใส่ไฟล์ App.config ในแอปพลิเคชันที่อ้างอิง dll ไลบรารีของคลาสของคุณ
ตัวอย่างเช่นสมมติว่าเรามีไลบรารีคลาสชื่อ MyClasses.dll ซึ่งใช้ไฟล์ app.config ดังนี้:
string connect =
ConfigurationSettings.AppSettings["MyClasses.ConnectionString"];
ตอนนี้สมมติว่าเรามี Windows Application ชื่อ MyApp.exe ซึ่งอ้างอิง MyClasses.dll มันจะมี App.config ที่มีรายการเช่น:
<appSettings>
<add key="MyClasses.ConnectionString"
value="Connection string body goes here" />
</appSettings>
หรือ
ไฟล์ xml เทียบเท่ากับ app.config ที่ดีที่สุด ใช้ xml ซีเรียลไลซ์ / ดีซีเรียลไลซ์ตามต้องการ คุณสามารถเรียกมันว่าทุกสิ่งที่คุณต้องการ หากการกำหนดค่าของคุณเป็น "คงที่" และไม่จำเป็นต้องเปลี่ยนแปลงคุณสามารถเพิ่มลงในโครงการเป็นทรัพยากรที่ฝังตัวได้
หวังว่าจะให้ความคิดบางอย่าง
ConfigurationSettings
ตอนนี้ล้าสมัยและถูกแทนที่ด้วยConfigurationManager
ดังนั้นตอนนี้จะเทียบเท่าConfigurationManager.AppSettings
ไฟล์การกำหนดค่าเป็นแอปพลิเคชันที่กำหนดขอบเขตและไม่ได้กำหนดขอบเขตการประกอบ ดังนั้นคุณจะต้องใส่ส่วนการกำหนดค่าของห้องสมุดในไฟล์การกำหนดค่าของทุกแอปพลิเคชันที่ใช้ห้องสมุดของคุณ
ที่กล่าวว่าไม่ใช่วิธีที่ดีที่จะได้รับการกำหนดค่าจากไฟล์การกำหนดค่าของแอปพลิเคชันโดยเฉพาะอย่างยิ่งappSettings
ส่วนในไลบรารีคลาส หากห้องสมุดของคุณต้องการพารามิเตอร์พวกเขาอาจจะถูกส่งผ่านเป็นข้อโต้แย้งวิธีในการสร้างวิธีการจากโรงงาน ฯลฯ โดยใครก็ตามที่โทรห้องสมุดของคุณ สิ่งนี้จะป้องกันไม่ให้แอปพลิเคชันเรียกใช้รายการการกำหนดค่าซ้ำที่ตั้งใจโดยไลบรารีคลาส
ที่กล่าวไว้ว่าไฟล์การกำหนดค่า XML นั้นมีประโยชน์อย่างยิ่งดังนั้นสิ่งที่ดีที่สุดที่ฉันพบคือการใช้ส่วนกำหนดค่าแบบกำหนดเอง คุณได้กำหนดค่าไลบรารีของคุณในไฟล์ XML ที่อ่านและแยกวิเคราะห์โดยเฟรมเวิร์กโดยอัตโนมัติและหลีกเลี่ยงอุบัติเหตุที่อาจเกิดขึ้น
คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับการกำหนดค่าส่วนที่กำหนดเองในMSDNและฟิล Haack มีบทความที่ดีกับพวกเขา
appSettings
หัวข้อที่กำหนดเองตามการประชุมเป็นทางเลือกที่ดี มันเป็นสิ่งที่สมาชิก ASP.NET ใช้กัน
public class ConfigMan
{
#region Members
string _assemblyLocation;
Configuration _configuration;
#endregion Members
#region Constructors
/// <summary>
/// Loads config file settings for libraries that use assembly.dll.config files
/// </summary>
/// <param name="assemblyLocation">The full path or UNC location of the loaded file that contains the manifest.</param>
public ConfigMan(string assemblyLocation)
{
_assemblyLocation = assemblyLocation;
}
#endregion Constructors
#region Properties
Configuration Configuration
{
get
{
if (_configuration == null)
{
try
{
_configuration = ConfigurationManager.OpenExeConfiguration(_assemblyLocation);
}
catch (Exception exception)
{
}
}
return _configuration;
}
}
#endregion Properties
#region Methods
public string GetAppSetting(string key)
{
string result = string.Empty;
if (Configuration != null)
{
KeyValueConfigurationElement keyValueConfigurationElement = Configuration.AppSettings.Settings[key];
if (keyValueConfigurationElement != null)
{
string value = keyValueConfigurationElement.Value;
if (!string.IsNullOrEmpty(value)) result = value;
}
}
return result;
}
#endregion Methods
}
เพื่อทำสิ่งใดฉันจะปรับคำตอบที่ดีที่สุดให้กับชั้นเรียน การใช้งานเป็นสิ่งที่ชอบ:
ConfigMan configMan = new ConfigMan(this.GetType().Assembly.Location);
var setting = configMan.GetAppSetting("AppSettingsKey");
หากคุณเพิ่มการตั้งค่าให้กับโครงการห้องสมุดคลาสใน Visual Studio (คุณสมบัติโครงการการตั้งค่า) มันจะเพิ่มไฟล์ app.config ให้กับโครงการของคุณด้วย userSettings / applicatioNSettings ส่วนที่เกี่ยวข้องและค่าเริ่มต้นสำหรับการตั้งค่าเหล่านี้จากการตั้งค่าของคุณ ไฟล์.
อย่างไรก็ตามไฟล์การกำหนดค่านี้จะไม่ถูกใช้ในรันไทม์ แต่ไลบรารีคลาสจะใช้ไฟล์การกำหนดค่าของแอปพลิเคชันการโฮสต์
ฉันเชื่อว่าเหตุผลหลักในการสร้างไฟล์นี้คือเพื่อให้คุณสามารถคัดลอก / วางการตั้งค่าลงในไฟล์กำหนดค่าของแอปพลิเคชันโฮสต์
ขณะนี้ฉันกำลังสร้างปลั๊กอินสำหรับแบรนด์ซอฟต์แวร์ค้าปลีกซึ่งจริงๆแล้วเป็นไลบรารีระดับ. net ตามความต้องการของแต่ละปลั๊กอินจะต้องมีการกำหนดค่าโดยใช้ไฟล์ config หลังจากทำการวิจัยและทดสอบเล็กน้อยฉันได้รวบรวมคลาสต่อไปนี้ มันทำงานได้อย่างไม่มีที่ติ โปรดทราบว่าฉันไม่ได้ใช้การจัดการข้อยกเว้นในเครื่องในกรณีของฉันเพราะฉันได้รับการยกเว้นในระดับที่สูงขึ้น
อาจต้องมีการปรับแต่งบางอย่างเพื่อให้ได้จุดทศนิยมในกรณีทศนิยมและทวีคูณ แต่มันใช้งานได้ดีสำหรับ CultureInfo ของฉัน ...
static class Settings
{
static UriBuilder uri = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase);
static Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(uri.Path);
static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings");
static NumberFormatInfo nfi = new NumberFormatInfo()
{
NumberGroupSeparator = "",
CurrencyDecimalSeparator = "."
};
public static T Setting<T>(string name)
{
return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
}
}
ตัวอย่างไฟล์ App.Config
<add key="Enabled" value="true" />
<add key="ExportPath" value="c:\" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />
การใช้งาน:
somebooleanvar = Settings.Setting<bool>("Enabled");
somestringlvar = Settings.Setting<string>("ExportPath");
someintvar = Settings.Setting<int>("Seconds");
somedoublevar = Settings.Setting<double>("Ratio");
มอบเครดิตให้กับ Shadow Wizard & MattC
เพื่อตอบคำถามเดิมฉันมักจะเพิ่มไฟล์กำหนดค่าในโครงการทดสอบของฉันเป็นลิงก์ จากนั้นคุณสามารถใช้แอ็ตทริบิวต์ DeploymentItem เพื่อเพิ่มไปยังโฟลเดอร์ Out ของการทดสอบการทำงาน
[TestClass]
[DeploymentItem("MyProject.Cache.dll.config")]
public class CacheTest
{
.
.
.
.
}
เพื่อตอบสนองต่อความคิดเห็นที่ว่าชุดประกอบไม่สามารถเจาะจงโครงการได้พวกเขาสามารถและให้ความยืดหยุ่นที่ดีเยี่ยม เมื่อทำงานกับกรอบ IOC
ฉันประสบปัญหาเดียวกันและแก้ไขโดยสร้างคลาสแบบสแตติกParameters
หลังจากเพิ่มไฟล์ Application Configuration ลงในโครงการ:
public static class Parameters
{
// For a Web Application
public static string PathConfig { get; private set; } =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "web.config");
// For a Class Library
public static string PathConfig { get; private set; } =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "LibraryName.dll.config");
public static string GetParameter(string paramName)
{
string paramValue = string.Empty;
using (Stream stream = File.OpenRead(PathConfig))
{
XDocument xdoc = XDocument.Load(stream);
XElement element = xdoc.Element("configuration").Element("appSettings").Elements().First(a => a.Attribute("key").Value == paramName);
paramValue = element.Attribute("value").Value;
}
return paramValue;
}
}
จากนั้นรับพารามิเตอร์ดังนี้:
Parameters.GetParameter("keyName");
แอสเซมบลีไม่มีไฟล์ app.config ของตัวเอง พวกเขาใช้ไฟล์ app.config ของแอปพลิเคชันที่ใช้งานอยู่ ดังนั้นหากแอสเซมบลีของคุณคาดหวังบางสิ่งในไฟล์กำหนดค่าจากนั้นตรวจสอบให้แน่ใจว่าไฟล์กำหนดค่าของแอปพลิเคชันของคุณมีรายการเหล่านั้นอยู่ในนั้น
หากแอสเซมบลีของคุณถูกใช้งานโดยหลายแอปพลิเคชันดังนั้นแต่ละแอปพลิเคชันเหล่านั้นจะต้องมีรายการเหล่านั้นในไฟล์ app.config
สิ่งที่ฉันจะแนะนำให้คุณทำคือกำหนดคุณสมบัติของคลาสในชุดประกอบสำหรับค่าเหล่านั้น
private string ExternalServicesUrl
{
get
{
string externalServiceUrl = ConfigurationManager.AppSettings["ExternalServicesUrl"];
if (String.IsNullOrEmpty(externalServiceUrl))
throw new MissingConfigFileAppSettings("The Config file is missing the appSettings entry for: ExternalServicesUrl");
return externalServiceUrl;
}
}
ExternalServicesUrl ที่นี่คุณสมบัติได้รับค่าจากไฟล์ config ของแอปพลิเคชัน หากแอปพลิเคชันที่ใช้แอสเซมบลีนี้หายไปการตั้งค่าในไฟล์กำหนดค่าคุณจะได้รับข้อยกเว้น o ชัดเจนว่ามีบางอย่างหายไป
MissingConfigFileAppSettings เป็นข้อยกเว้นที่กำหนดเอง คุณอาจต้องการที่จะโยนข้อยกเว้นที่แตกต่างกัน
แน่นอนว่าการออกแบบที่ดีกว่านั้นจะใช้วิธีการของคลาสเหล่านั้นเพื่อให้ค่าเหล่านั้นเป็นพารามิเตอร์แทนที่จะใช้การตั้งค่าไฟล์ config วิธีนี้ทำให้แอปพลิเคชันที่ใช้คลาสเหล่านี้สามารถตัดสินใจได้ว่าจะให้คุณค่าเหล่านี้จากที่ไหนและอย่างไร
ใช้เพิ่มรายการที่มีอยู่ให้เลือกการกำหนดค่าแอพจากโครงการ dll ก่อนที่จะคลิกเพิ่มให้ใช้ลูกศรลงทางด้านขวาของปุ่มเพิ่มเพื่อ "เพิ่มเป็นลิงค์"
ฉันทำสิ่งนี้ตลอดเวลาใน dev ของฉัน
คำนำ : ฉันใช้ NET 2.0;
วิธีการแก้ปัญหาที่โพสต์โดยYiannis Leoussisเป็นที่ยอมรับ แต่ฉันมีปัญหากับมัน
ครั้งแรกstatic AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings");
ผลตอบแทนที่เป็นโมฆะ ฉันต้องเปลี่ยนมันเป็นstatic AppSettingSection = myDllConfig.AppSettings;
จากนั้นผู้return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
ไม่มีการจับยกเว้น ดังนั้นฉันจึงเปลี่ยนมัน
try
{
return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
}
catch (Exception ex)
{
return default(T);
}
มันใช้งานได้ดีมาก แต่ถ้าคุณมี dll ที่แตกต่างกันคุณจะต้องเขียนใหม่ทุกครั้งที่มีรหัสสำหรับชุดประกอบทุกชุด ดังนั้นนี่คือรุ่นของฉันสำหรับคลาสที่จะสร้างอินสแตนซ์ทุกครั้งที่คุณต้องการ
public class Settings
{
private AppSettingsSection _appSettings;
private NumberFormatInfo _nfi;
public Settings(Assembly currentAssembly)
{
UriBuilder uri = new UriBuilder(currentAssembly.CodeBase);
string configPath = Uri.UnescapeDataString(uri.Path);
Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(configPath);
_appSettings = myDllConfig.AppSettings;
_nfi = new NumberFormatInfo()
{
NumberGroupSeparator = "",
CurrencyDecimalSeparator = "."
};
}
public T Setting<T>(string name)
{
try
{
return (T)Convert.ChangeType(_appSettings.Settings[name].Value, typeof(T), _nfi);
}
catch (Exception ex)
{
return default(T);
}
}
}
สำหรับการกำหนดค่า:
<add key="Enabled" value="true" />
<add key="ExportPath" value="c:\" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />
ใช้เป็น:
Settings _setting = new Settings(Assembly.GetExecutingAssembly());
somebooleanvar = _settings.Setting<bool>("Enabled");
somestringlvar = _settings.Setting<string>("ExportPath");
someintvar = _settings.Setting<int>("Seconds");
somedoublevar = _settings.Setting<double>("Ratio");
เท่าที่ฉันทราบคุณจะต้องคัดลอก + วางส่วนที่คุณต้องการจากไลบรารี. config ลงในไฟล์. config ของแอปพลิเคชัน คุณจะได้รับ 1 app.config ต่อหนึ่งอินสแตนซ์ที่สามารถเรียกใช้งานได้
ทำไมไม่ใช้:
[ProjectNamespace].Properties.Settings.Default.[KeyProperty]
สำหรับ C #My.Settings.[KeyProperty]
สำหรับ VB.NETคุณต้องอัปเดตคุณสมบัติเหล่านั้นด้วยสายตาขณะออกแบบผ่าน:
[Solution Project]->Properties->Settings
ใช้จากการกำหนดค่าจะต้องง่ายมากเช่นนี้:
var config = new MiniConfig("setting.conf");
config.AddOrUpdate("port", "1580");
if (config.TryGet("port", out int port)) // if config exist
{
Console.Write(port);
}
สำหรับรายละเอียดเพิ่มเติมดูMiniConfig
string exeConfigPath = this.GetType().Assembly.Location;
เป็นอย่างเช่น:string exeConfigPath = @"C:\MyFolder\DllFolder\ExeName.exe";