0

Solved as below!! - I have multiple WPF projects with individual App.Config with custom sections. All custom sections have the same structure.

For one project, I used ConfigurationManager and created Custom ConfigurationSection, ConfigurationCollection, ConfigurationElement and everything works fine for that project.

Then I moved my custom configuration classes in a class library so that I can use them in all the projects, but now I am getting 'System.TypeInitializationException' error when I run the project. This seems to be because now ConfigurationManager can't locate the App.

I can copy paste the class in all the projects and it works fine but I don't want to do that. May be I am probably missing something obvious. Any help is very much appreciated. Thanks!!!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Configuration;

namespace WordAddinForms
{

    public class CustomConfig : ConfigurationSection
    {
    public static readonly CustomConfig Settings =
        (CustomConfig)ConfigurationManager.GetSection("custom-configuration"); 

    [ConfigurationProperty("activities")]
    public ActivityElementCollection Activities
    {
        get { return (ActivityElementCollection)base["activities"]; }
    }       
    }

    [ConfigurationCollection(typeof(ActivityElement), AddItemName = "activity",
    CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
    public class ActivityElementCollection : ConfigurationElementCollection, IEnumerable<ActivityElement>
    {
    IEnumerator<ActivityElement> IEnumerable<ActivityElement>.GetEnumerator()
    {
        return this.OfType<ActivityElement>().GetEnumerator();
    }
    public override ConfigurationElementCollectionType CollectionType
    {
        get { return ConfigurationElementCollectionType.BasicMap; }
    }
    protected override string ElementName
    {
        get { return "activity"; }
    }
    protected override ConfigurationElement CreateNewElement()
    {
        return new ActivityElement();
    }
    protected override object GetElementKey(ConfigurationElement element)
    {
        return (element as ActivityElement).Name;
    }

    public ActivityElement this[int index]
    {
        get { return (ActivityElement)base.BaseGet(index); }
        set
        {
        if (base.BaseGet(index) != null)
        {
            base.BaseRemoveAt(index);
        }
        base.BaseAdd(index, value);
        }
    }
    public ActivityElement this[string name]
    {
        get { return (ActivityElement)base.BaseGet(name); }
    }

    }

    public class ActivityElement : ConfigurationElement
    {
    [ConfigurationProperty("name", DefaultValue = "String.Empty")]
    public string Name
    {
        get { return (string)base["name"]; }
    }        
    [ConfigurationProperty("location", DefaultValue = "String.Empty")]
    public string Location
    {
        get { return (string)base["location"]; }
    }       

    [ConfigurationProperty("files")]
    public FileElementCollection Files
    {
        get { return (FileElementCollection)base["files"]; }
    }
    }

    [ConfigurationCollection(typeof(FileElement), AddItemName = "file",
    CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
    public class FileElementCollection : ConfigurationElementCollection, IEnumerable<FileElement>
    {
    IEnumerator<FileElement> IEnumerable<FileElement>.GetEnumerator()
    {
        return this.OfType<FileElement>().GetEnumerator();
    }
    public override ConfigurationElementCollectionType CollectionType
    {
        get { return ConfigurationElementCollectionType.BasicMap; }
    }
    protected override string ElementName
    {
        get { return "file"; }
    }
    protected override ConfigurationElement CreateNewElement()
    {
        return new FileElement();
    }
    protected override object GetElementKey(ConfigurationElement element)
    {
        return (element as FileElement).Name;
    }

    public FileElement this[int index]
    {
        get { return (FileElement)base.BaseGet(index); }
        set
        {
        if (base.BaseGet(index) != null)
        {
            base.BaseRemoveAt(index);
        }
        base.BaseAdd(index, value);
        }
    }
    public FileElement this[string name]
    {
        get { return (FileElement)base.BaseGet(name); }
    }
    }

    public class FileElement : ConfigurationElement
    {
    [ConfigurationProperty("name", DefaultValue = "String.Empty")]
    public string Name
    {
        get { return (string)base["name"]; }
    }

    /// <remarks />
    [ConfigurationProperty("location", DefaultValue = "String.Empty")]
    public string Location
    {
        get { return (string)base["location"]; }
    }        
    }
}

Edit -- App.config file -

<?xml version="1.0" ?>
<custom-configuration>
 <activities>
  <activity name="Activities" location=".\Activity\">
    <files>
      <file name="Running" location=".Running\"/>
      <file name="Sports" location=".Sports\"/>
      <file name="Fun" location=".Fun\"/>
      <file name="Exercise" location=".Exercise\"/>     
    </files>
  </activity>  
 </activities>
</custom-configuration>

Question rephrased - So,

1) I have multiple app.config for various projects in the structure mentioned above

2) I have created custom configuration classes as shown in the code above

I need to put them in a class library\shared library so that I can reuse the classes instead of copy-pasting them in individual projects. When I put the classes in shared library, the project rebuilds fine but it fails when I run it.

Answer - Clearly I need to get the basics right. After shifting the code to class library, I had to update app.config accordingly as the namespace and location for the class has now changed. Sorry for the inconvenience. Basically, I needed to update "type" of the section as the class now belongs to different assembly.

ShipOfTheseus
  • 234
  • 1
  • 10
  • If you're not going to share the code, at least share the stack trace. – Ant P Apr 28 '14 at 16:48
  • you'll still need the .dll unless it's a GAC assembly. – T McKeown Apr 28 '14 at 16:49
  • Sorry, I have added the configuration code that I want to use in a class library\shared library as above. It works fine if I include the whole code as a part of the projectA. i.e. when I access - CustomConfig.Settings.Categories["mycategory"] in projectA, the code works fine. But if I separate it and put it in the class library(classLibraryA), I cant use CustomConfig.Settings.Categories["mycategory"] in projectA anymore. – ShipOfTheseus Apr 28 '14 at 17:13

1 Answers1

0

Answer - Clearly I need to get the basics right. After shifting the code to class library, I had to update app.config accordingly as the namespace and location for the class has now changed. Sorry for the inconvenience. Basically, I needed to update "type" of the section as the class now belongs to different assembly.

ShipOfTheseus
  • 234
  • 1
  • 10