Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ConfigurationElementCollection and Linq

I've written some custom configuration collections, elements etc. Now, I'd like to do a simple Linq statement:

ServerDetails servers = ConfigurationManager.GetSection("serverDetails") as ServerDetails;
var server = from s in servers
             where s.Name == serverName
             select s;

I get the error:

Could not find an implementation of the query pattern for source type 'MyNamespace.ServerDetails'. 'Where' not found.

The ServerElement has two properties:

public class ServerElement : ConfigurationElement
{
    [ConfigurationProperty("ip")]
    public string IP
    {
        get { return (string)base["ip"]; }
        set { base["ip"] = value; }
    }

    [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
    public string Name
    {
        get { return (string)base["name"]; }
        set { base["name"] = value; }
    }
}

ServerDetails

public sealed class ServerDetails : ConfigurationSection
{
    [ConfigurationProperty("ServerCollection")]
    [ConfigurationCollection(typeof(ServerCollection), AddItemName = "add")]
    public ServerCollection ServerCollection
    {
        get { return this["ServerCollection"] as ServerCollection; }
    }
}

ServerCollection

public sealed class ServerCollection : ConfigurationElementCollection
{
    public void Add(ServerElement ServerElement)
    {
        this.BaseAdd(ServerElement);
    }

    public override ConfigurationElementCollectionType CollectionType
    {
        get { return ConfigurationElementCollectionType.AddRemoveClearMap; }
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new ServerElement();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((ServerElement)element).Name;
    }
}

Am I missing something? Do I need to add something in so that I can use Linq with a custom configuration element?

By the way, I have using System.Linq; defined as I'm using it else where within the same class.

like image 531
Neil Knight Avatar asked Dec 07 '11 10:12

Neil Knight


3 Answers

Okay, given that it's all weakly typed, you'll need to either call Cast<> or OfType<> explicitly, or give an explicit type to the range variable. You'll also need to specify the ServerCollection property on your ServerDetails. For example:

ServerDetails servers = (ServerDetails) ConfigurationManager.GetSection("serverDetails");
var server = from ServerElement s in servers.ServerCollection
             where s.Name == serverName
             select s;
like image 153
Jon Skeet Avatar answered Nov 01 '22 00:11

Jon Skeet


Using Brian Gideon's simple example of yield return in his IEnumerable<T> implementation, I was able to enumerate over my ConfigurationElementCollection.

It would look something like this (using the original question):

public sealed class ServerCollection : ConfigurationElementCollection,
    IEnumerable<ServerElement>
{
    ...

    public new IEnumerator<ServerElement> GetEnumerator()
    {
        foreach (var key in this.BaseGetAllKeys())
        {
            yield return (ServerElement)BaseGet(key);
        }
    }
}

While I was NOT getting the error:

Could not find an implementation of the query pattern for source type 'MyNamespace.ServerDetails'. 'Where' not found

...I was not able to iterate over my ConfigurationElementCollection using LINQ, either. This solution fixed my problem so that I could use LINQ to iteration over my collection.

like image 24
cat5dev Avatar answered Nov 01 '22 02:11

cat5dev


 var server = ((ServerDetails) ConfigurationManager.GetSection("serverDetails")).
      ServerCollection.Cast<ServerElement>().FirstOrDefault(x => x.Name == serverName);
like image 4
Jay Shah Avatar answered Nov 01 '22 00:11

Jay Shah