Tôi đã tạo phần cấu hình tùy chỉnh cho plugin DLL lưu trữ XML .config trong tệp riêng biệt (từ tệp ứng dụng chính).Phần cấu hình tùy chỉnh .NET: Configuration.GetSection ném 'không thể định vị assembly' ngoại lệ
Dưới đây là một mẫu của các lớp phần tùy chỉnh:
using System;
using System.Configuration;
namespace PluginFramework.MyConfiguration
{
public class MyConfigurationSettings : ConfigurationSection
{
private Configuration _Config = null;
#region ConfigurationProperties
/// <summary>
/// A custom XML section for an application's configuration file.
/// </summary>
[ConfigurationProperty("MyProjects", IsDefaultCollection = true)]
public MyProjectConfigurationCollection MyProjects
{
get { return (MyProjectConfigurationCollection) base["MyProjects"]; }
}
// ...
#endregion
/// <summary>
/// Private Constructor used by our factory method.
/// </summary>
private MyConfigurationSettings() : base() {
// Allow this section to be stored in user.app. By default this is forbidden.
this.SectionInformation.AllowExeDefinition =
ConfigurationAllowExeDefinition.MachineToLocalUser;
}
// ...
#region Static Members
/// <summary>
/// Gets the current applications <MyConfigurationSettings> section.
/// </summary>
/// <param name="ConfigLevel">
/// The <ConfigurationUserLevel> that the config file
/// is retrieved from.
/// </param>
/// <returns>
/// The configuration file's <MyConfigurationSettings> section.
/// </returns>
public static MyConfigurationSettings GetSection (ConfigurationUserLevel ConfigLevel)
{
string appDataPath = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string localDataPath = System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
System.Configuration.ExeConfigurationFileMap exeMap = new ExeConfigurationFileMap();
exeMap.ExeConfigFilename = System.IO.Path.Combine(appDataPath, @"MyCompany\MyPluginApp\Default.config");
exeMap.RoamingUserConfigFilename = System.IO.Path.Combine(appDataPath, @"MyCompany\MyPluginApp\Roaming.config");
exeMap.LocalUserConfigFilename = System.IO.Path.Combine(localDataPath, @"MyCompany\MyPluginApp\Local.config");
System.Configuration.Configuration Config = ConfigurationManager.OpenMappedExeConfiguration(exeMap,ConfigLevel);
MyConfigurationSettings myConfigurationSettings = null;
try {
myConfigurationSettings = (MyConfigurationSettings)Config.GetSection("MyConfigurationSettings");
}
catch (System.Exception ex) {
// ConfigurationErrorsException caught here ...
}
if (myConfigurationSettings == null) {
myConfigurationSettings = new MyConfigurationSettings();
Config.Sections.Add("MyConfigurationSettings", myConfigurationSettings); }
}
if(myConfigurationSettings != null) {
myConfigurationSettings._Config = Config;
}
return myConfigurationSettings;
}
#endregion
}
} // PluginFramework.MyConfiguration
XML .config tạo ra khi tiết kiệm thời gian 1 trông như thế này:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- The exception complains about the following line (assembly attributes are compliant): -->
<section name="MyConfigurationSettings" type="PluginFramework.MyConfiguration.MyConfigurationSettings, PluginFramework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" allowDefinition="Everywhere" allowExeDefinition="MachineToLocalUser" />
</configSections>
<MyConfigurationSettings>
<!-- Config properties are serialized fine according MyConfigurationSettings
properties marked with the ConfigurationProperty attribute ... -->
<MyProjects>
<MyProjectConfiguration GUID="{4307AC92-8180-4686-9322-830312ED59AB}">
<!-- ... more complex configuration elements -->
</MyProjectConfiguration>
</MyProjects>
</MyConfigurationSettings>
</configuration>
Khi XML này đang cố gắng để được nạp bằng Config.GetSection()
trên các lần chạy tiếp theo, tôi bắt một số ConfigurationErrorsException
tại dòng được đánh dấu trong mẫu XML, cho biết rằng assembly MyPlugin
hoặc một trong các phụ thuộc của nó không thể được định vị (xin vui lòng tha thứ rằng tôi không đăng ngoại lệ gốc mes hiền nhân, nhưng tôi có nó chỉ bằng tiếng Đức, và nghi ngờ văn bản này sẽ hữu ích ở đây). Ngoại lệ bên trong xuất phát từ System.IO
trong khi cố gắng tải assembly và lấy phản xạ để giải quyết kiểu lớp 'MyConfigurationSettings'.
Để chính xác tình hình, mã từ trên được đặt bên trong một khuôn khổ DLL (lắp ráp), do đó được tham chiếu bởi plugin DLL thực tế được tải từ ứng dụng chính.
Sơ đồ UML sau đây minh họa mối quan hệ với một số thành phần:
Sau khi nhìn xung quanh một chút về vấn đề này, tôi có cảm giác đó là cần thiết để tên mạnh (dấu hiệu) lắp ráp xuất khẩu lớp MyConfigurationSettings
(tức PluginFramework
) và đăng ký nó với GAC. Tôi đã không thử điều này được nêu ra, và muốn tránh bước này vì nhiều lý do (trước khi biết nếu nó thậm chí có thể giúp đỡ và đó là sự lựa chọn duy nhất để giải quyết vấn đề).
Vì vậy, đây là những câu hỏi (xin lỗi tôi đặt 4 câu hỏi ở đây, nhưng chúng liên quan chặt chẽ đến mức không tạo ra các câu hỏi SO riêng biệt cho chúng).
Tôi có thể giải quyết vấn đề lỗi định vị bằng cách đặt tên đúng cách lắp ráp được đề cập và đăng ký nó với GAC không?
Ngẫu nhiên, quá trình lắp ráp quản lý cấu hình bị phàn nàn, được đảm bảo được tải (vì nó tự gọi là số
Configuration.GetSection()
).
Có thể có cách nào để đăng ký lắp ráp hoặc loại cấu hình phù hợp với/hoặc serializers một cách rõ ràng với lớp họcConfigurationManager
hoặcConfguration
?Tôi cũng quan tâm đến thông tin thêm về Hans Passant's comment đề cập đến điều này có thể là một vấn đề gây ra bởi cách lắp ráp (chính) được tải từ ứng dụng chính. Tôi không có quyền kiểm soát cơ chế này, và nếu điều này gây ra hành vi này vốn dĩ tôi muốn biết liệu có cách giải quyết hợp lý không?
Một ý tưởng khác (nếu bất cứ điều gì ở trên không hiển thị một cách) là hoàn toàn quản lý định dạng XML cấu hình nguyên bản (sử dụng hỗ trợ xê-ri XML) và từ nơi tải và hợp nhất các tệp cấu hình. Nếu đây là lựa chọn thích hợp nhất, bất cứ ai có thể cung cấp cho con trỏ tốt cách thực hiện điều này một cách hiệu quả (ít nhất là mã cần thiết để quản lý đường dẫn và hợp nhất)?
Cập nhật:
Vì không ai có vẻ để có thể cung cấp cho cái nhìn sâu sắc hơn về câu hỏi này (s) (2 câu trả lời không thực sự làm cho tôi thêm), tôi thay đổi để lựa chọn từ 4., làm tất cả bằng tay.
Một điều tôi cho bạn biết chắc chắn - nó không cần phải ở trong GAC. Trước tiên, hãy đảm bảo rằng Trình xử lý mục của bạn sống trong cùng thư mục với phần còn lại của mã. Thứ hai, hãy đảm bảo bạn sử dụng trình quản lý cấu hình phù hợp. Thứ ba, hãy chắc chắn rằng bạn có tất cả {} tương ứng với các thuộc tính trong "MyConfigurationSettings" của bạn. Đây là bắt đầu ... Và thứ tư! Nhìn vào lớp của bạn ... Tôi không nghĩ bạn sử dụng nó đúng. Bạn cần tài sản ở đó, không phải "GetSection". Đây là toàn bộ ý tưởng mà bạn gọi GetSection và khung tìm thấy bạn phần xử lý bên phải, nơi bạn chỉ phải làm tài sản -call –
Nếu ứng dụng chính được đặt tên mạnh thì bất kỳ assembly nào nó tham chiếu cũng phải được đặt tên mạnh. – groverboy
@ T.S. Âm thanh đầy hứa hẹn! Hãy xem một số chỉnh sửa để cải thiện câu hỏi. DLL framework được đề cập nằm trong cùng thư mục với plugin DLL, nhưng không nằm trong cùng thư mục với ứng dụng chính có thể thực thi được. Tôi nghĩ rằng điểm của bạn về các thuộc tính cấu hình có thể không liên quan (ít nhất là cho ngoại lệ đặc biệt này, nó phàn nàn chính xác về dòng tôi đã đánh dấu trong XML .config). Về việc sử dụng phương thức 'GetSection()', cái này chỉ dành cho thuận tiện cho việc truy cập vào phần cụ thể này, tôi không biết tôi có thể thay thế cái này bằng bất động sản ở đâu ... –