Подходит ли динамический linq для этого сценария? - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть простой интерфейс, IDevice

public interface IDevice{
    string Id{ get; }
}

У меня есть список объектов, которые реализуют IDevice

List<IDevice> devices;

Пример двух типов объектов в этомВот список:

public class BatteryDevice : IDevice{
    public string Id{ get; private set; }
    public int StateOfCharge{ get; set; }
}

public class GridDevice : IDevice{
    public string Id{ get; private set; }
    public decimal Voltage{ get; set; }
}

Я хочу разрешить пользователю устанавливать условие в тексте с помощью SQL-запроса, например, так:

Id = 'Battery1' AND StateOfCharge > 95

, чтобы я мог прочитать эти условия из текстаКонфигурационный файл и сравните его со списком устройств, использующих динамический LINQ, следующим образом:

var matches = devices.Where("Id = 'Battery1' AND StateOfCharge > 95");

Это не работает, потому что (конечно) LINQ потерпит неудачу при попытке получить значение для StateOfCharge изGridDevice

Я чувствую себя немного не в своей тарелке и ищу способ достичь своей цели и буду признателен за любой вклад.

Ответы [ 2 ]

2 голосов
/ 06 ноября 2019

Вы можете написать:

var matches = devices
              .OfType<BatteryDevice>()
              .Where(device => device.Id == "Battery1" && device.StateOfCharge > 95)
              .ToList();

. Он выбирает все устройства из List из IDevice типа BatteryDevice, которые соответствуют требуемому условию, и возвращает List<BatteryDevice>, содержащий элементы полученного Linq. последовательность запросов.

Вы можете использовать ToList или нет, в зависимости от того, что вы планируете делать с результатом.

Если нет, то результат типа IEnumerable<BatteryDevice>.

Чтобы иметь List из IDevice, вы можете использовать:

.ToList<IDevice>();

Или вы можете написать:

var matches = (IEnumerable<IDevice>)devices...

Без Linq

var matches = new List<IDevice>();
foreach ( var device in devices )
  if ( device is BatteryDevice )
  {
    var battery = (BatteryDevice)device;
    if ( battery.Id == "Battery1" && battery.StateOfCharge > 95 )
      matches.Add(battery);
  }
0 голосов
/ 06 ноября 2019

Я думаю, что вы все еще можете использовать динамический Linq или Linq. Сначала проверьте тип.

Конечно, это не может работать. не безопасный тип.

var filter1 = devices.Where(q => (q as GridDevice).Voltage == 0);

Это будет работать, потому что первый фильтр проверяет тип. Вы не получите объект ref error.

var filtered=devices.Where(q => q.GetType() == typeof(GridDevice) && (q as GridDevice).Voltage==0);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...