tags:

views:

106

answers:

2

Hello All,

I have made some progress on the problem I posted about yesterday, so I am rewriting the post.

My problem appears to be related to my use of generics. Here's the relevant part of App.config (formatted with whitespace for readability):

<configSections>
    <section
        name="NA5300ResolverSynchroDevices"
        type="InfrastructureModule.DeviceConfiguration.DeviceConfigurationSection
             &lt;NA5300ResolverSynchroModule.NA5300ResolverSynchroConfigurationElement&gt;,
             NA5300ResolverSynchroModule">
    </section>
</configSections>

<NA5300ResolverSynchroDevices>
    <Device deviceName="AzResolverSynchro" busAddress="7"/>
    <Device deviceName="ElResolverSynchro" busAddress="8"/>
</NA5300ResolverSynchroDevices>

Here's the class I'm trying to map to the configuration section:

namespace InfrastructureModule.DeviceConfiguration
{
    public class DeviceConfigurationSection<T> : ConfigurationSection
           where T : DeviceConfigurationElement, new()
    {
        [ConfigurationProperty("", IsDefaultCollection = true, IsKey = false)]
        public DeviceConfigurationElementCollection<T> Devices
        {
            get { return (DeviceConfigurationElementCollection<T>) base[""]; }
            set { base[""] = value; }
        }
    }
}

Here's the C# code that tries to access the config file:

DeviceConfigurationSection<NA5300ResolverSynchroConfigurationElement> devices =
    ConfigurationManager.GetSection("NA5300ResolverSynchroDevices") as
    DeviceConfigurationSection<NA5300ResolverSynchroConfigurationElement>;

Here's the exception text I'm getting:

An error occurred creating the configuration section handler for NA5300ResolverSynchroDevices: Could not load type 'InfrastructureModule.DeviceConfiguration.DeviceConfigurationSection<NA5300ResolverSynchroModule.NA5300ResolverSynchroConfigurationElement>' from assembly 'NA5300ResolverSynchroModule'.

I know that in C# generics are instantiated at runtime rather than at compile time (unlike C++). I do not yet know enough about generics to understand what assembly a runtime-generated type is considered to live in when the generic type and the instantiating type live in different assemblies. Above, I told the runtime to look for it in assembly NA5300ResolverSynchroModule. I've also tried telling it to look for it in assembly InfrastructureModule. Neither works.

I am attempting to use a genric type because I will have many config sections for which the corresponding ConfigurationSection-derived types will all be of the form shown above. I want to avoid code duplication.

Can anybody see why my approach is failing and how I can fix it?

A: 

I believe my problem was rooted in the fact that the runtime-generated type I tried to map to a configuration section does not live in an assembly. So, I created a type that does live in an assmebly.

namespace NA5300ResolverSynchroModule
{
    public class NA5300ResolverSynchroDeviceConfigurationSection :
      DeviceConfigurationSection<NA5300ResolverSynchroConfigurationElement>
    {
    }
}

I can reference NA5300ResolverSynchroDeviceConfigurationSection just fine in App.config.

Dave
It's not the location of your generic type, it's actually the syntax in your app.config.
Philip Rieck
A: 

Your problem is actually how you've referenced the generic type.

Instead of (shortened):

<section name="..."
type="InfrastructureModule.DeviceConfiguration.DeviceConfigurationSection
             &lt;NA5300ResolverSynchroModule.NA5300ResolverSynchroConfigurationElement&gt;,
             NA5300ResolverSynchroModule" />

Try

<section name="..."
type="InfrastructureModule.DeviceConfiguration.DeviceConfigurationSection`1[[NA5300ResolverSynchroModule.NA5300ResolverSynchroConfigurationElement, NA5300ResolverSynchroModule]],
             NA5300ResolverSynchroModule" />

Note the `1[[...]] rather than <...> or &lt;...&gt; part for the generic type. The part inside the [[...]] can be a full type definition as well - like namespace.class,assembly,token.

The 1 is "generic type with one type parameter". If the type takes 2 "aka SomeType<T,V>", use 2. Note that you should put "type, assembly" in the double square brackets, not just "type"

Philip Rieck
Well, it turns out I'm still not quite there. I tried both a forward tick (') and a backward tick (`), and I tried both InfrastructureModule and NA5300ResolverSynchroModule for the assembly. That's four combinations, and all resulted in an exception still indicating the required type could not be found in the assembly I specified. I think this is really close though. Is there some syntactic tweak that needs to be made to your suggestion?
Dave
For the record it's backtick, 1, double square brackets: `1[[ - Are both of the types in the same assembly?
Philip Rieck
I've edited with a bit more info.
Philip Rieck
Your latest suggestions have led me to success. Here's what ultimately ended up working: type="InfrastructureModule.DeviceConfiguration.DeviceConfigurationSection`1[[NA5300ResolverSynchroModule.DeviceConfiguration.NA5300ResolverSynchroConfigurationElement, NA5300ResolverSynchroModule]], InfrastructureModule"/>As can be seen above, the generic type and the instantiating type are not in the same assembly.Thank you very kindly for the help; this is much better than the solution I had come up with!
Dave