Có tương đương app.config
với thư viện (DLL) không? Nếu không, cách dễ nhất để lưu trữ các cài đặt cấu hình dành riêng cho thư viện là gì? Vui lòng xem xét rằng thư viện có thể được sử dụng trong các ứng dụng khác nhau.
Có tương đương app.config
với thư viện (DLL) không? Nếu không, cách dễ nhất để lưu trữ các cài đặt cấu hình dành riêng cho thư viện là gì? Vui lòng xem xét rằng thư viện có thể được sử dụng trong các ứng dụng khác nhau.
Câu trả lời:
Bạn có thể có tệp cấu hình riêng biệt, nhưng bạn sẽ phải đọc "thủ công", ConfigurationManager.AppSettings["key"]
sẽ chỉ đọc cấu hình của cụm đang chạy.
Giả sử bạn đang sử dụng Visual Studio làm IDE, bạn có thể nhấp chuột phải vào dự án mong muốn → Thêm → Mục mới → Tệp cấu hình ứng dụng
Điều này sẽ thêm App.config
vào thư mục dự án, đặt các thiết lập của bạn trong đó dưới <appSettings>
phần. Trong trường hợp bạn không sử dụng Visual Studio và thêm tệp theo cách thủ công, hãy đảm bảo đặt tên như vậy: DLLName.dll.config , nếu không, đoạn mã dưới đây sẽ không hoạt động chính xác.
Bây giờ để đọc từ tập tin này có chức năng như vậy:
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;
}
Và để sử dụng nó:
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");
...
}
Bạn cũng sẽ phải thêm tham chiếu đến không gian tên System.Configuration để có sẵn lớp Cấu hình Trình quản lý.
Khi xây dựng dự án, ngoài DLL bạn cũng sẽ có DllName.dll.config
tệp, đó là tệp bạn phải xuất bản với chính DLL.
Trên đây là mã mẫu cơ bản, đối với những người quan tâm đến một ví dụ quy mô đầy đủ, vui lòng tham khảo câu trả lời khác này .
Thật không may, bạn chỉ có thể có một tệp app.config cho mỗi lần thực thi, vì vậy nếu bạn có DLL được liên kết với ứng dụng của mình, họ không thể có tệp app.config của riêng họ.
Giải pháp là:
Bạn không cần đặt tệp App.config trong dự án của Thư viện lớp.
Bạn đặt tệp App.config trong ứng dụng đang tham chiếu dll của thư viện lớp của bạn.
Ví dụ: giả sử chúng ta có một thư viện lớp có tên MyClass.dll sử dụng tệp app.config như vậy:
string connect =
ConfigurationSettings.AppSettings["MyClasses.ConnectionString"];
Bây giờ, giả sử chúng ta có Ứng dụng Windows có tên MyApp.exe tham chiếu MyClass.dll. Nó sẽ chứa một App.config với một mục như:
<appSettings>
<add key="MyClasses.ConnectionString"
value="Connection string body goes here" />
</appSettings>
HOẶC LÀ
Một tệp xml tương đương tốt nhất cho app.config. Sử dụng xml serialize / deserialize khi cần thiết. Bạn có thể gọi nó là những gì bạn muốn. Nếu cấu hình của bạn là "tĩnh" và không cần thay đổi, bạn cũng có thể thêm nó vào dự án dưới dạng tài nguyên nhúng.
Hy vọng nó mang lại một số ý tưởng
ConfigurationSettings
bây giờ đã lỗi thời và được thay thế bởi ConfigurationManager
, vì vậy, tương đương bây giờ sẽ làConfigurationManager.AppSettings
Các tệp cấu hình là phạm vi ứng dụng và không có phạm vi lắp ráp. Vì vậy, bạn sẽ cần đặt các phần cấu hình thư viện của mình trong tệp cấu hình của mọi ứng dụng đang sử dụng thư viện của bạn.
Điều đó nói rằng, không phải là một thực hành tốt để có được cấu hình từ tệp cấu hình của ứng dụng, đặc biệt là appSettings
phần, trong một thư viện lớp. Nếu thư viện của bạn cần các tham số, có lẽ chúng sẽ được chuyển qua làm đối số phương thức trong hàm tạo, phương thức nhà máy, v.v. bởi bất cứ ai đang gọi thư viện của bạn. Điều này ngăn các ứng dụng gọi vô tình sử dụng lại các mục cấu hình được thư viện lớp mong đợi.
Điều đó nói rằng, các tệp cấu hình XML cực kỳ tiện dụng, do đó, sự thỏa hiệp tốt nhất mà tôi tìm thấy là sử dụng các phần cấu hình tùy chỉnh. Bạn có thể đặt cấu hình thư viện của mình trong một tệp XML được khung tự động đọc và phân tích cú pháp và bạn tránh được các tai nạn tiềm ẩn.
Bạn có thể tìm hiểu thêm về các phần cấu hình tùy chỉnh trên MSDN và Phil Haack cũng có một bài viết hay về chúng.
appSettings
phần tùy chỉnh dựa trên quy ước , cung cấp một sự thay thế tuyệt vời; Rốt cuộc, đó là khá nhiều những gì Thành viên ASP.NET sử dụng.
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
}
Chỉ cần một cái gì đó để làm, tôi tái cấu trúc câu trả lời hàng đầu vào một lớp. Cách sử dụng là một cái gì đó như:
ConfigMan configMan = new ConfigMan(this.GetType().Assembly.Location);
var setting = configMan.GetAppSetting("AppSettingsKey");
Nếu bạn thêm Cài đặt vào dự án Thư viện lớp trong Visual Studio (Thuộc tính dự án, Cài đặt), nó sẽ thêm tệp app.config vào dự án của bạn với các phần userSinstall / applicationatioNSinstall có liên quan và các giá trị mặc định cho các cài đặt này từ Cài đặt của bạn tập tin.
Tuy nhiên, tệp cấu hình này sẽ không được sử dụng trong thời gian chạy - thay vào đó thư viện lớp sử dụng tệp cấu hình của ứng dụng lưu trữ.
Tôi tin rằng lý do chính để tạo tệp này là để bạn có thể sao chép / dán cài đặt vào tệp cấu hình của ứng dụng máy chủ.
Tôi hiện đang tạo các plugin cho một thương hiệu phần mềm bán lẻ, thực sự là các thư viện lớp .net. Theo yêu cầu, mỗi plugin cần được cấu hình bằng tệp cấu hình. Sau một chút nghiên cứu và thử nghiệm, tôi đã biên soạn lớp sau. Nó làm công việc hoàn hảo. Lưu ý rằng tôi đã không thực hiện xử lý ngoại lệ cục bộ trong trường hợp của mình bởi vì, tôi bắt ngoại lệ ở mức cao hơn.
Một số điều chỉnh có thể cần thiết để có được dấu thập phân đúng, trong trường hợp số thập phân và nhân đôi, nhưng nó hoạt động tốt cho CultureInfo của tôi ...
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);
}
}
Mẫu tệp App.Config
<add key="Enabled" value="true" />
<add key="ExportPath" value="c:\" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />
Sử dụng:
somebooleanvar = Settings.Setting<bool>("Enabled");
somestringlvar = Settings.Setting<string>("ExportPath");
someintvar = Settings.Setting<int>("Seconds");
somedoublevar = Settings.Setting<double>("Ratio");
Tín dụng cho Shadow Wizard & MattC
Để trả lời cho câu hỏi ban đầu, tôi thường thêm tệp cấu hình trong dự án thử nghiệm của mình dưới dạng liên kết; sau đó bạn có thể sử dụng thuộc tính DeploymentItem để thêm vào thư mục Out của lần chạy thử.
[TestClass]
[DeploymentItem("MyProject.Cache.dll.config")]
public class CacheTest
{
.
.
.
.
}
Đáp lại những bình luận rằng Hội đồng không thể là dự án cụ thể, họ có thể và nó cung cấp đặc biệt linh hoạt tuyệt vời. khi làm việc với các khung IOC.
Tôi đã đối mặt với cùng một vấn đề và giải quyết nó bằng cách tạo một lớp tĩnh Parameters
sau khi thêm Tệp cấu hình ứng dụng vào dự án:
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;
}
}
Sau đó nhận được một tham số như thế này:
Parameters.GetParameter("keyName");
các hội đồng không có tệp app.config của riêng họ. Họ sử dụng tệp app.config của ứng dụng đang sử dụng chúng. Vì vậy, nếu hội đồng của bạn đang mong đợi một số thứ nhất định trong tệp cấu hình, thì hãy đảm bảo rằng tệp cấu hình của ứng dụng của bạn có các mục đó trong đó.
Nếu tập hợp của bạn đang được sử dụng bởi nhiều ứng dụng thì mỗi ứng dụng đó sẽ cần phải có các mục đó trong tệp app.config của chúng.
Những gì tôi khuyên bạn nên làm là xác định các thuộc tính trên các lớp trong cụm của bạn cho các giá trị đó chẳng hạn
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;
}
}
Ở đây, thuộc tính InternalServiceUrl nhận giá trị của nó từ tệp cấu hình của ứng dụng. Nếu bất kỳ ứng dụng nào sử dụng cụm này bị thiếu thì cài đặt đó trong tệp cấu hình, bạn sẽ nhận được một ngoại lệ o rõ ràng là thiếu một cái gì đó.
MissingConfigFileAppS Settings là một Ngoại lệ tùy chỉnh. Bạn có thể muốn ném một ngoại lệ khác.
Tất nhiên, một thiết kế tốt hơn sẽ là phương thức của các lớp đó được cung cấp các giá trị đó dưới dạng tham số thay vì dựa vào cài đặt tệp cấu hình. Bằng cách đó, các ứng dụng sử dụng các lớp này có thể quyết định từ đâu và làm thế nào chúng cung cấp các giá trị này.
Lời mở đầu : Tôi đang sử dụng NET 2.0;
Các giải pháp được đăng bởi Yiannis Leoussis là chấp nhận được nhưng tôi đã có một số vấn đề với nó.
Đầu tiên, static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings");
trả về null. Tôi phải đổi nó thànhstatic AppSettingSection = myDllConfig.AppSettings;
Sau đó, return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
không có một lưu ý cho Ngoại lệ. Vì vậy, tôi đã thay đổi nó
try
{
return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
}
catch (Exception ex)
{
return default(T);
}
Điều này hoạt động rất tốt nhưng nếu bạn có một dll khác, bạn phải viết lại mỗi lần mã cho mỗi hội đồng. Vì vậy, đây là phiên bản của tôi cho một Class để khởi tạo mỗi khi bạn cần.
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);
}
}
}
Đối với cấu hình:
<add key="Enabled" value="true" />
<add key="ExportPath" value="c:\" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />
Sử dụng nó như:
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");
Theo như tôi biết, bạn phải sao chép + dán các phần bạn muốn từ thư viện .config vào tệp .config ứng dụng. Bạn chỉ nhận được 1 app.config cho mỗi phiên bản thực thi.
Tại sao không sử dụng:
[ProjectNamespace].Properties.Settings.Default.[KeyProperty]
cho C #My.Settings.[KeyProperty]
cho VB.NETBạn chỉ cần cập nhật trực quan các thuộc tính đó tại thời điểm thiết kế thông qua:
[Solution Project]->Properties->Settings
sử dụng từ các cấu hình phải rất rất dễ dàng như thế này:
var config = new MiniConfig("setting.conf");
config.AddOrUpdate("port", "1580");
if (config.TryGet("port", out int port)) // if config exist
{
Console.Write(port);
}
để biết thêm chi tiết, xem MiniConfig
string exeConfigPath = this.GetType().Assembly.Location;
thành một cái gì đó như:string exeConfigPath = @"C:\MyFolder\DllFolder\ExeName.exe";