代码之家  ›  专栏  ›  技术社区  ›  ehcanadian

自定义配置节:无法加载文件或程序集

  •  21
  • ehcanadian  · 技术社区  · 16 年前

    我很难访问配置文件中的自定义配置部分。

    正在从作为插件加载的.dll中读取配置文件。我使用 Configuration Section Designer vs.

    命名空间为“importconfiguration”。configurationSection类是“importWorkflows”。总成是进口的。

    XML:

      <configSections>
        <section name="importWorkflows" type="ImportConfiguration.ImportWorkflows, ImportEPDMAddin"/>
      </configSections>
    

    每当我尝试读取配置时,我都会得到错误:

    为导入工作流创建配置节处理程序时出错:无法加载文件或程序集“importedpmaddin.dll”或其依赖项之一。系统找不到指定的文件。

    该dll与可执行文件不在同一目录中,因为加载插件的软件会将该dll及其依赖项放在自己的目录中。(我无法控制。)

    我将singleton实例的代码编辑为:

    string path = System.Reflection.Assembly.GetCallingAssembly().CodeBase;
    path = path.Replace("file:///", "");
    System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenExeConfiguration(path);
    return configuration.GetSection(ImportWorkflowsSectionName) as ImportConfiguration.ImportWorkflows;
    

    我也尝试过使用一个简单的namevaluefilesectionhandler,但是我得到一个异常,它不能加载文件或程序集“system”。

    我读过很多博客文章和文章,听起来好像可以从中读取一个dll的配置文件,但我就是不能让它工作。有什么想法吗?谢谢。

    7 回复  |  直到 9 年前
        1
  •  35
  •   AJ.    14 年前

    不幸的是,您需要 ImportEPDMAddin 程序集与可执行文件位于同一文件夹中,或位于与您正在使用的.NET Framework相关的.NET Framework文件夹中(即C:\Windows\Microsoft.NET\Framework\v2.0.50727),或在全局程序集缓存中注册。

    唯一的另一个选项是,如果知道包含配置处理程序的定义类的程序集的路径,则可以在不引用类似以下内容的情况下加载该程序集:

    //Class global
    private Assembly configurationDefiningAssembly;
    
    protected TConfig GetCustomConfig<TConfig>(string configDefiningAssemblyPath, 
        string configFilePath, string sectionName) where TConfig : ConfigurationSection
    {
        AppDomain.CurrentDomain.AssemblyResolve += new 
            ResolveEventHandler(ConfigResolveEventHandler);
        configurationDefiningAssembly = Assembly.LoadFrom(configDefiningAssemblyPath);
        var exeFileMap = new ExeConfigurationFileMap();
        exeFileMap.ExeConfigFilename = configFilePath;
        var customConfig = ConfigurationManager.OpenMappedExeConfiguration(exeFileMap, 
            ConfigurationUserLevel.None);
        var returnConfig = customConfig.GetSection(sectionName) as TConfig;
        AppDomain.CurrentDomain.AssemblyResolve -= ConfigResolveEventHandler;
        return returnConfig;
    }
    
    protected Assembly ConfigResolveEventHandler(object sender, ResolveEventArgs args)
    {
        return configurationDefiningAssembly;
    }
    

    确保处理assemblyresolve事件,因为这将引发一个没有它的异常。

        2
  •  6
  •   j0k gauthamp    12 年前

    在主应用程序配置文件中,添加以下内容(插件是程序集的加载文件夹)。可以使用多个半冒号分隔的路径。

    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <probing privatePath=".;.\Plugins"/>
        </assemblyBinding>
    </runtime>
    

    取自 http://msdn.microsoft.com/en-us/library/823z9h8w%28v=vs.90%29.aspx

        3
  •  4
  •   rileywhite cgatian    12 年前

    为了扩展AJ的优秀答案,这里有一个定制类来帮助注册和删除全局事件的开销。

    public sealed class AddinCustomConfigResolveHelper : IDisposable
    {
        public AddinCustomConfigResolveHelper(
            Assembly addinAssemblyContainingConfigSectionDefinition)
        {
            Contract.Assert(addinAssemblyContainingConfigSectionDefinition != null);
    
            this.AddinAssemblyContainingConfigSectionDefinition =
                addinAssemblyContainingConfigSectionDefinition;
    
            AppDomain.CurrentDomain.AssemblyResolve +=
                this.ConfigResolveEventHandler;
        }
    
        ~AddinCustomConfigResolveHelper()
        {
            this.Dispose(false);
        }
    
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        private void Dispose(bool isDisposing)
        {
            AppDomain.CurrentDomain.AssemblyResolve -= this.ConfigResolveEventHandler;
        }
    
        private Assembly AddinAssemblyContainingConfigSectionDefinition { get; set; }
    
        private Assembly ConfigResolveEventHandler(object sender, ResolveEventArgs args)
        {
            // often the name provided is partial...this will match full or partial naming
            if (this.AddinAssemblyContainingConfigSectionDefinition.FullName.Contains(args.Name))
            {
                return this.AddinAssemblyContainingConfigSectionDefinition;
            }
    
            return null;
        }
    }
    

    我建议在using语句中创建一个实例,如下所示:

    // you'll need to populate these two variables
    var configuration = GetConfiguration();
    var assembly = GetAssemblyContainingConfig();
    
    using(new AddinCustomConfigResolveHelper(assembly))
    {
        return (MyConfigSection)configuration.GetSection("myConfigSection");
    }
    
        4
  •  1
  •   Mark Coleman    16 年前

    您可以验证主机应用程序的配置文件中是否正确设置了探测路径吗?可能当前应用程序域中未加载所需的引用。

    Assembly Binding ->Probing

        5
  •  0
  •   Matthew Ferreira    16 年前

    您确定要先加载DLL吗?也许与 Assembly.LoadFile("PATH") ?

    如果您不能让System.Configuration中的类正常工作,那么您可以使用xmlDocument手动解析配置文件。使用xpaths使获取数据更加容易。例如(假设您的路径变量在上面):

    var document = new XmlDocument();
    document.Load(path);
    var node = document.SelectSingleNode("configuration/importWorkflows/add[@name='KEY']");
    // Do whatever with node
    
        6
  •  0
  •   this    11 年前

    我试着用莱利怀特的增刊来回答AJ的问题,但我发现这对我不起作用。

    在我的场景中,自定义配置节类已经在当前正在执行的程序集中,并且尝试加载它会导致堆栈溢出。我也不想把它放在GAC中,即使它确实解决了OP报告的问题。

    最后,我发现这对我的目标来说足够有效。也许其他人会觉得它有用:

    public class CustomConfigurationSection : ConfigurationSection {
      public CustomConfigurationSection()
      {
        var reader = XmlReader.Create(<path to my dll.config>);
        reader.ReadToDescendant("CustomConfigurationSection");
        base.DeserializeElement(reader,false);
      }
    
      // <rest of code>
    }
    
        7
  •  0
  •   wintondeshong    9 年前

    必须使用模块/插件程序集的完全限定类型字符串,该字符串位于探测目录中,因此可以找到它。以EntityFramework为例…

    不正确的:

    type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework"
    

    对的

    type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
    
    推荐文章