Конфигурация ElementCollection и Linq - PullRequest
30 голосов
/ 07 декабря 2011

Я написал несколько пользовательских коллекций конфигурации, элементы и т. Д. Теперь я хотел бы сделать простое утверждение Linq:

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

Я получаю ошибку:

Не удалось найти реализацию шаблона запроса для типа источника 'MyNamespace.ServerDetails'. «Где» не найдено.

ServerElement имеет два свойства:

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;
    }
}

Я что-то упустил? Нужно ли что-то добавить, чтобы я мог использовать Linq с пользовательским элементом конфигурации?

Кстати, у меня using System.Linq; определено, поскольку я использую его где-то в том же классе.

Ответы [ 3 ]

38 голосов
/ 07 декабря 2011

Хорошо, учитывая, что все они слабо типизированы, вам нужно либо явно вызвать Cast<> или OfType<>, либо дать явный тип переменной диапазона.Вам также необходимо указать свойство ServerCollection в вашем ServerDetails.Например:

ServerDetails servers = (ServerDetails) ConfigurationManager.GetSection("serverDetails");
var server = from ServerElement s in servers.ServerCollection
             where s.Name == serverName
             select s;
17 голосов
/ 08 апреля 2015

Используя простой пример Брайана Гидеона из доходности в его реализации IEnumerable , я смог перечислить мой ConfigurationElementCollection.

Это будет выглядеть примерно так (используя оригинальный вопрос):

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

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

Пока я НЕ получаю сообщение об ошибке:

Не удалось найти реализацию шаблона запроса для типа источника «MyNamespace.ServerDetails». «Где» не найдено

... Мне не удалось перебрать мою коллекцию ConfigurationElementCollection с помощью LINQ. Это решение исправило мою проблему, так что я мог использовать LINQ для итерации по своей коллекции.

0 голосов
/ 09 сентября 2018
 var server = ((ServerDetails) ConfigurationManager.GetSection("serverDetails")).
      ServerCollection.Cast<ServerElement>().FirstOrDefault(x => x.Name == serverName);
...