moving the config files for a dll to the app that

2019-01-15 20:03发布

问题:

I have a web app that has search functionality. The search algorithm is compiled to a separate dll. In the C# code for the search algorithm, I am using strings held in a settings file to point to the directory where the search index resides. Once the search code is compiled, the settings info is incorporated in Search.dll.config which is put in the bin directory along with Search.dll. Now in my web app, I add Search.dll to the references. The config file is not added into the web app. However the web app runs fine and knows where the file is. Because inside Settings.Designer it uses the DefaultSettingValueAttribute to assign a default if the config file is not there.

How do I also add Search.dll.config to my web app so the operator can change the location of the index files on the server as need be?

Thanks

EDIT:

I tried to add the config file to my deployment folder. But ASP.NET puts the dlls in a directory at C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root...... and the config file doesn't get copied there. So at this point I have no idea how to include the config file with my code.

Thanks for your help.

Note:

I have been using the following code to get the values of the config file into the app. However, it depends on the dll and the config file to be in the same folder, which I do not know how to accomplish.

    var executingAssembly = System.Reflection.Assembly.GetExecutingAssembly();
    var location = executingAssembly.Location; //C:\MyApp\bin\Debug\Search.dll
    var config = ConfigurationManager.OpenExeConfiguration(location);
    var sections = config.Sections; //count of this is 21
    ConfigurationSectionGroup csg = config.GetSectionGroup("applicationSettings");
    ConfigurationSectionCollection csc = csg.Sections;
    ConfigurationSection cs = csc.Get("Search.Properties.Settings");

回答1:

Your best bet is to add the config to the web project directly. .NET doesn't really support configuration associated with a library in the way you are attempting; and this is by design. Other users of your library may need different configuration. Mark the file as being content that should be copied to the output folder.

EDIT:

To do this set "Build Action" to "Content" and "Copy to Output Directory" as "Copy if newer" in the file properties. You can discover the file in the bin folder using HttpRuntime.BinDirectory. You may want to pass this location to your library rather than have the library assume it's running in a web project.

Alternatively, just embed the config you need in web.config (config files have a facility to break out settings into a separate file as well).

Finally, you could consider embedding the file as a resource.

EDIT:

Looking at the code you are using, just move it into web.config. Much easier, and idiomatic. Once it's in web.config just use ConfigurationManager.GetSection() to read your section.

Incidentally, there's a free configuration section designer that makes creating the classes to support custom configuration sections very easy. Look in the VS Extensions Online Gallery here:

http://visualstudiogallery.msdn.microsoft.com/2a69f74e-83df-4eb0-8cac-cd83b451cd1d?SRC=VSIDE



回答2:

The ideal way is to remove the configuration dependency from DLLs. A dll is designed to be used by an application and configuration belongs to application not a dll.

In most of the scenarios, you can get rid of depending on/reading from config in dll code by using dependency injection either through DI container or through manual compose.

if your search dll depend on the settings, make the settings as a dependency for your dll entry point class and proceed with dll code assuming somehow your entry point class gets it's settings.

Then, you can supply the settings value from your application, be it web/windows/console and by reading from configuration file/db/web service/file system.

sample code:

In dll:

 public interface ISearcherDirectorySettings
{
    string[] SearchIndexPointers { get; }
}

public class Searcher
{
    private readonly ISearcherDirectorySettings _searchDirctorySettings;

    public Searcher(ISearcherDirectorySettings searchDirtorySettings)
    {
        _searchDirctorySettings = searchDirtorySettings;
    }

    public void SearchAlgorithm()
    {
        var indexes = _searchDirctorySettings.SearchIndexPointers;
        // search code
    }
}

In your application:

public class SearcherDirectorySettings : ISearcherDirectorySettings
{
    private readonly string[] _pointers;
    public SearcherDirectorySettings(string[] pointers)
    {
        _pointers = pointers;
    }

    public string[] SearchIndexPointers
    {
        get { return _pointers; }
    }
}

public class ApplicationRootClass //Owns configuration file
{
    const string FirstPointerKey = "File1";
    const string SecondPointerKey = "File2";

    private Func<string, string> _getFromConfig = key => ConfigurationManager.AppSettings[key];

    public ApplicationRootClass()
    {
        var searcherDirectorySettings = new SearcherDirectorySettings(new[] { _getFromConfig(FirstPointerKey),_getFromConfig(SecondPointerKey) });

        var searcher = new Searcher(searcherDirectorySettings);
        searcher.SearchAlgorithm();
    }
}

With this, you can achieve "fail fast". you can have the search dlls used in any application and it will be the responsibility of the application to supply settings value.

If you end up using the dll in multiple applications/projects and duplicating the settings class code, have a utility component that does the job or move the settings class into the dll but leave the instantiation of settings class to the application.



回答3:

Here's how you do what you want to do, as opposed to what some think you should do:

(sorry I'm working in vb at the moment)

Say the dll is named mycompany.mynamespace.dll

  1. Rename the app.config file in your dll project to mycompany.mynamespace.dll.config
  2. In its properties, say Copy If Newer
  3. Use this code (within the dll) to access your setting:

        Dim appConfig = ConfigurationManager.OpenExeConfiguration(Me.GetType.Assembly.Location)
        _WorkingDirectory = appConfig.AppSettings.Settings("WorkingDirectory").Value