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.
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;
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.
var server = ((ServerDetails) ConfigurationManager.GetSection("serverDetails")).
ServerCollection.Cast<ServerElement>().FirstOrDefault(x => x.Name == serverName);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With