Всем привет.Интересна такая вещь,можно ли получить знаки сравнения (> < = >= <=) из string и потом использовать их?
public class Main
{
List<ListItem> ls = new List<ListItem>();
private void FilterButtonClick(...)
{
if(Combobox1.SelectedText == "Id")
{
if(Combobox2.Selectedtext == ">=")
{
var its = ls.Where(z=>z.Id>=Convert.ToInt32(Textbox1.Text)).ToList();
for(int i = 0;i<its.Count;i++)
{
datagridview.Rows.Add(Its[i].Name);
}
else if(Combobox2.Selectedtext == "<=")
{
var its = ls.Where(z=>z.Id<=Convert.ToInt32(Textbox1.Text)).ToList();
for(int i = 0;i<its.Count;i++)
{
datagridview.Rows.Add(Its[i].Name);
}
}
}
else if(Combobox1.SelectedText == "Age")
{
if(Combobox2.Selectedtext == ">=")
{
var its = ls.Where(z=>z.Age>=Convert.ToInt32(Textbox1.Text)).ToList();
for(int i = 0;i<its.Count;i++)
{
datagridview.Rows.Add(Its[i].Name);
}
else if(Combobox2.Selectedtext == "<=")
{
var its = ls.Where(z=>z.Age<=Convert.ToInt32(Textbox1.Text)).ToList();
for(int i = 0;i<its.Count;i++)
{
datagridview.Rows.Add(Its[i].Name);
}
}
}
}
}
public class ListItem
{
string Name;
int Id;
int Age;
int birthday_date;
int Height;
int Weight;
}
Знаю код лучше было делать с Switch.Но писал на сайте и так было удобней.
Например, для int
:
Func<int, int, bool> ConstructRelation(string s)
{
switch (s)
{
case ">": return (Func<int, int, bool>)((a, b) => a > b);
case "<": return (Func<int, int, bool>)((a, b) => a < b);
case "==": return (Func<int, int, bool>)((a, b) => a == b);
case ">=": return (Func<int, int, bool>)((a, b) => a >= b);
case "<=": return (Func<int, int, bool>)((a, b) => a <= b);
default: throw new ArgumentException("Unknown relation");
}
}
Пользоваться так:
Func<int, int, bool> rel = ConstructRelation(">");
Console.WriteLine(rel(5, 4)); // выводит True
Рабочий код: http://ideone.com/UWgKlU
Пользоваться можно примерно так:
Func<ListItem, int> firstGetter = null;
switch (Combobox1.SelectedText)
{
case "Id": firstGetter = z => z.Id; break;
case "Age": firstGetter = z => z.Age; break;
// тут остальные значения
default: throw new ArgumentException();
}
int secondValue = Convert.ToInt32(Textbox1.Text);
Func<int, int, bool> rel = ConstructRelation(Combobox2.Selectedtext);
var its = ls.Where(z => rel(firstGetter(z), secondValue));
foreach(var item in its)
{
datagridview.Rows.Add(item.Name);
}
Через Scripting API:
> Install-Package Microsoft.CodeAnalysis.CSharp.Scripting
[пакет с пачкой зависимостей, может долго скачиваться]
И после этого можно собирать код на лету:
using System;
using Microsoft.CodeAnalysis.CSharp.Scripting;
namespace ConsoleApplication27
{
public class Globals
{
public int X;
public int Y;
}
class Program
{
static void Main(string[] args)
{
var globals = new Globals { X = 1, Y = 2 };
string op = ">";
Console.WriteLine(CSharpScript.EvaluateAsync<bool>($"X{op}Y", globals: globals).Result);
}
}
}
При реальном использовании стоит добавить кэширование и принудительную компиляцию через Compile()
+ RunAsync
вместо EvaluateAsync
.
Для трех знаков сравнения это как из пушки по воробьям. Если объектов мало - то самый простой вариант - switch по знакам сравнения + reflection для извлечения свойства по имени. Дешево, сердито и читабельно.
Если объектов много - то можно пропробовать собрать лямбду для сравнения на лету:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Linq;
namespace ConsoleApplication27
{
class ListItem
{
public int Id { get; set; }
public int Age { get; set; }
public string Name { get; set; }
}
class Program
{
static readonly Dictionary<string, ExpressionType> opsMap =
new Dictionary<string, ExpressionType>
{
{ ">=", ExpressionType.GreaterThanOrEqual },
{ "==", ExpressionType.Equal },
{ "<=", ExpressionType.LessThanOrEqual }
};
static void Main(string[] args)
{
string operation = ">=";
string fieldToCompare = "Age";
string textToCompare = "15";
List<ListItem> ls = new List<ListItem>
{
new ListItem { Age = 10, Name = "a" },
new ListItem { Age = 20, Name = "b" },
};
var listItemType = typeof(ListItem);
var propToCompare = listItemType.GetProperty(fieldToCompare);
var valueToCompare = Convert.ChangeType(textToCompare, propToCompare.PropertyType);
// собираем лямбду x => x.Age >= 15
var param = Expression.Parameter(listItemType);
var predicate = Expression.Lambda<Func<ListItem, bool>>(
Expression.MakeBinary(opsMap[operation],
Expression.Property(param, propToCompare),
Expression.Constant(valueToCompare)),
param); // .Compile и кэш при необходимости
// убрать AsQueryable если выше используется Compile
var result = ls.AsQueryable().Where(predicate).ToList();
}
}
}
Виртуальный выделенный сервер (VDS) становится отличным выбором
Каким образом можно узнать, что в списке или массиве не содержится ни одного элемента?
Нужно вызвать свойства из своего приложения (путем нажатия кнопки) окна cmd с использованием c# или winapi по примеру скриншота, вся информации...