Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有没有一种方法可以重复使用LINQ语句,但改变对该属性调用的属性和方法?_C#_Linq - Fatal编程技术网

C# 有没有一种方法可以重复使用LINQ语句,但改变对该属性调用的属性和方法?

C# 有没有一种方法可以重复使用LINQ语句,但改变对该属性调用的属性和方法?,c#,linq,C#,Linq,我有下面的代码片段,我似乎不能想出一个优雅的方法来重构它,所以我没有违反复制/粘贴编程。请注意这个片段并不完整,但我相信它应该有必要的信息来提供适当的上下文。任何帮助都将不胜感激 public static void Main() { IEnumerable<Person> dataSet = new List<Person> { new Person{ ID = "1", PrimaryName = "Prim", SecondaryNa

我有下面的代码片段,我似乎不能想出一个优雅的方法来重构它,所以我没有违反复制/粘贴编程。请注意这个片段并不完整,但我相信它应该有必要的信息来提供适当的上下文。任何帮助都将不胜感激

public static void Main()
{
    IEnumerable<Person> dataSet = new List<Person>
    {
        new Person{ ID = "1", PrimaryName = "Prim", SecondaryName = "Sec"},
        new Person{ ID = "2", PrimaryName = "test", SecondaryName = "Sec2"},
        new Person{ ID = "3", PrimaryName = "test", SecondaryName = "Sec3"}
    };
    string attribute = "LastName";
    OperatorValue queryOperator = OperatorValue.Equal;
    string value = "test";

    switch (attribute)
    {
        case ("LastName"):
            if (queryOperator.Equals(OperatorValue.Equal))
            {
                dataSet = dataSet.Where(p => p.PrimaryName.Equals(value));
            }
            else if (queryOperator.Equals(OperatorValue.NotEquals))
            {
                dataSet = dataSet.Where(p => !p.PrimaryName.Equals(value));
            }
            else if (queryOperator.Equals(OperatorValue.StartsWith))
            {
                dataSet = dataSet.Where(p => p.PrimaryName.StartsWith(value));
            }
            else
            {
                dataSet = dataSet.Where(p => p.PrimaryName.Contains(value));
            }
            break;
        case ("FirstName"):
            if (queryOperator.Equals(OperatorValue.Equal))
            {
                dataSet = dataSet.Where(p => p.SecondaryName.Equals(value));
            }
            else if (queryOperator.Equals(OperatorValue.NotEquals))
            {
                dataSet = dataSet.Where(p => !p.SecondaryName.Equals(value));
            }
            else if (queryOperator.Equals(OperatorValue.StartsWith))
            {
                dataSet = dataSet.Where(p => p.SecondaryName.StartsWith(value));
            }
            else
            {
                dataSet = dataSet.Where(p => p.SecondaryName.Contains(value));
            }
            break;
        case ("ID"):
            if (queryOperator.Equals(OperatorValue.Equal))
            {
                dataSet = dataSet.Where(p => p.ID.Equals(value));
            }
            else if (queryOperator.Equals(OperatorValue.NotEquals))
            {
                dataSet = dataSet.Where(p => !p.ID.Equals(value));
            }
            else if (queryOperator.Equals(OperatorValue.StartsWith))
            {
                dataSet = dataSet.Where(p => p.ID.StartsWith(value));
            }
            else
            {
                dataSet = dataSet.Where(p => p.ID.Contains(value));
            }
            break;
    }

    foreach (Person person in dataSet)
        Console.WriteLine(person.ID);
}

public enum OperatorValue
{
    Equal,
    NotEquals,
    StartsWith
}

public class Person
{
    public string ID { get; set; }
    public string SecondaryName { get; set; }
    public string PrimaryName { get; set; }
}
publicstaticvoidmain()
{
IEnumerable数据集=新列表
{
新人{ID=“1”,PrimaryName=“Prim”,SecondaryName=“Sec”},
新人{ID=“2”,PrimaryName=“test”,SecondaryName=“Sec2”},
新人{ID=“3”,PrimaryName=“test”,SecondaryName=“Sec3”}
};
字符串属性=“LastName”;
运算符值查询运算符=运算符值等于;
字符串值=“测试”;
开关(属性)
{
案例(“姓氏”):
if(queryOperator.Equals(OperatorValue.Equal))
{
dataSet=dataSet.Where(p=>p.PrimaryName.Equals(value));
}
else if(queryOperator.Equals(OperatorValue.NotEquals))
{
dataSet=dataSet.Where(p=>!p.PrimaryName.Equals(value));
}
else if(queryOperator.Equals(OperatorValue.StartsWith))
{
dataSet=dataSet.Where(p=>p.PrimaryName.StartsWith(value));
}
其他的
{
dataSet=dataSet.Where(p=>p.PrimaryName.Contains(value));
}
打破
案例(“名字”):
if(queryOperator.Equals(OperatorValue.Equal))
{
dataSet=dataSet.Where(p=>p.SecondaryName.Equals(value));
}
else if(queryOperator.Equals(OperatorValue.NotEquals))
{
dataSet=dataSet.Where(p=>!p.SecondaryName.Equals(value));
}
else if(queryOperator.Equals(OperatorValue.StartsWith))
{
dataSet=dataSet.Where(p=>p.SecondaryName.StartsWith(value));
}
其他的
{
dataSet=dataSet.Where(p=>p.SecondaryName.Contains(value));
}
打破
案件编号:
if(queryOperator.Equals(OperatorValue.Equal))
{
数据集=数据集,其中(p=>p.ID.Equals(value));
}
else if(queryOperator.Equals(OperatorValue.NotEquals))
{
数据集=数据集。其中(p=>!p.ID.Equals(value));
}
else if(queryOperator.Equals(OperatorValue.StartsWith))
{
dataSet=dataSet.Where(p=>p.ID.StartsWith(value));
}
其他的
{
dataSet=dataSet.Where(p=>p.ID.Contains(value));
}
打破
}
foreach(数据集中的人员)
Console.WriteLine(person.ID);
}
公共枚举运算符值
{
平等,
NotEquals,
开始
}
公共阶层人士
{
公共字符串ID{get;set;}
公共字符串SecondaryName{get;set;}
公共字符串PrimaryName{get;set;}
}

在switch语句中有更多的情况,我想用同样的方法来处理,所以你可以看到这开始变得很糟糕。我试图想出一个助手方法,我可以为每个案例调用它,但我完全被卡住了,没有主意。谢谢你的帮助

如果要使代码可重用,而不必每次都复制/粘贴,则需要按新属性进行筛选。您可以执行以下操作:

public static void Main()
{
    IEnumerable<Person> dataSet = new List<Person>
    {
        new Person{ ID = "1", PrimaryName = "Prim", SecondaryName = "Sec"},
        new Person{ ID = "2", PrimaryName = "test", SecondaryName = "Sec2"},
        new Person{ ID = "3", PrimaryName = "test", SecondaryName = "Sec3"}
    };
    string attribute = "LastName";
    OperatorValue queryOperator = OperatorValue.Equal;
    string value = "test";

    Func<Person, string> getter = GetFuncForProperty(attribute);
    dataSet = Filter(dataSet, getter, queryOperator, value);

    foreach (Person person in dataSet)
        Console.WriteLine(person.ID);
}

public static IEnumerable<Person> Filter(IEnumerable<Person> source, Func<Person, string> getter, OperatorValue operatorValue, string searchValue)
{
    switch (operatorValue)
    {
        case OperatorValue.Equal:
            return source.Where(p => getter.Invoke(p).Equals(searchValue));
        case OperatorValue.NotEquals:
            return source.Where(p => !getter.Invoke(p).Equals(searchValue));
        case OperatorValue.StartsWith:
            return source.Where(p => getter.Invoke(p).StartsWith(searchValue));
    }

    throw new ArgumentException(operatorValue.ToString() + " is not supported");
}

public static Func<Person, string> GetFuncForProperty(string propertyName)
{
    switch (propertyName)
    {
        case "ID":
            return (Person person) => person.ID;
        case "FirstName":
            return (Person person) => person.SecondaryName;
        case "LastName":
            return (Person person) => person.PrimaryName;
    }

    throw new ArgumentException(propertyName + " is not supported");
}

public enum OperatorValue
{
    Equal,
    NotEquals,
    StartsWith
}

public class Person
{
    public string ID { get; set; }
    public string SecondaryName { get; set; }
    public string PrimaryName { get; set; }
}
publicstaticvoidmain()
{
IEnumerable数据集=新列表
{
新人{ID=“1”,PrimaryName=“Prim”,SecondaryName=“Sec”},
新人{ID=“2”,PrimaryName=“test”,SecondaryName=“Sec2”},
新人{ID=“3”,PrimaryName=“test”,SecondaryName=“Sec3”}
};
字符串属性=“LastName”;
运算符值查询运算符=运算符值等于;
字符串值=“测试”;
Func getter=GetFuncForProperty(属性);
dataSet=过滤器(dataSet、getter、queryOperator、value);
foreach(数据集中的人员)
Console.WriteLine(person.ID);
}
公共静态IEnumerable筛选器(IEnumerable源、Func getter、运算符值、运算符值、字符串搜索值)
{
开关(运算符值)
{
大小写运算符值。等于:
返回source.Where(p=>getter.Invoke(p).Equals(searchValue));
案例运算符value.NotEquals:
返回source.Where(p=>!getter.Invoke(p).Equals(searchValue));
case operator value.StartsWith:
返回source.Where(p=>getter.Invoke(p).StartsWith(searchValue));
}
抛出新ArgumentException(不支持operatorValue.ToString()+);
}
公共静态Func GetFuncForProperty(字符串propertyName)
{
交换机(propertyName)
{
案例“ID”:
返回(Person)=>Person.ID;
案例“名字”:
return(Person)=>Person.SecondaryName;
案例“LastName”:
return(Person)=>Person.PrimaryName;
}
抛出新ArgumentException(不支持propertyName+);
}
公共枚举运算符值
{
平等,
NotEquals,
开始
}
公共阶层人士
{
公共字符串ID{get;set;}
公共字符串SecondaryName{get;set;}
公共字符串PrimaryName{get;set;}
}

如果您想使代码可重用,并且不必每次需要按新属性进行筛选时都复制/粘贴代码,请查看它在以下位置运行:

。您可以执行以下操作:

public static void Main()
{
    IEnumerable<Person> dataSet = new List<Person>
    {
        new Person{ ID = "1", PrimaryName = "Prim", SecondaryName = "Sec"},
        new Person{ ID = "2", PrimaryName = "test", SecondaryName = "Sec2"},
        new Person{ ID = "3", PrimaryName = "test", SecondaryName = "Sec3"}
    };
    string attribute = "LastName";
    OperatorValue queryOperator = OperatorValue.Equal;
    string value = "test";

    Func<Person, string> getter = GetFuncForProperty(attribute);
    dataSet = Filter(dataSet, getter, queryOperator, value);

    foreach (Person person in dataSet)
        Console.WriteLine(person.ID);
}

public static IEnumerable<Person> Filter(IEnumerable<Person> source, Func<Person, string> getter, OperatorValue operatorValue, string searchValue)
{
    switch (operatorValue)
    {
        case OperatorValue.Equal:
            return source.Where(p => getter.Invoke(p).Equals(searchValue));
        case OperatorValue.NotEquals:
            return source.Where(p => !getter.Invoke(p).Equals(searchValue));
        case OperatorValue.StartsWith:
            return source.Where(p => getter.Invoke(p).StartsWith(searchValue));
    }

    throw new ArgumentException(operatorValue.ToString() + " is not supported");
}

public static Func<Person, string> GetFuncForProperty(string propertyName)
{
    switch (propertyName)
    {
        case "ID":
            return (Person person) => person.ID;
        case "FirstName":
            return (Person person) => person.SecondaryName;
        case "LastName":
            return (Person person) => person.PrimaryName;
    }

    throw new ArgumentException(propertyName + " is not supported");
}

public enum OperatorValue
{
    Equal,
    NotEquals,
    StartsWith
}

public class Person
{
    public string ID { get; set; }
    public string SecondaryName { get; set; }
    public string PrimaryName { get; set; }
}
publicstaticvoidmain()
{
IEnumerable数据集=新列表
{
新人{ID=“1”,PrimaryName=“Prim”,SecondaryName=“Sec”},
新人{ID=“2”,PrimaryName=“test”,SecondaryName=“Sec2”},
新人{ID=“3”,PrimaryName=“test”,SecondaryName=“Sec3”}
};
字符串属性=“LastName”;
操作工
public static OperatorValue ToOperatorValue(this string queryOperator)
{
    // TODO: exception if input null
    return Enum.Parse(typeof(OperatorValue), queryOperator);

    // TODO: decide what to do if queryOperator has not existing enum value
}
string queryOperatorTxt = ...
OperatorValue operator = queryOperatorTxt.ToOperatorValue();
public static Expression<Func<Person, string>> ToPropertySelector(this string attributeTxt)
{
    // TODO: check incorrect parameters
    Expression<Func<Person, string>> propertySelector;
    switch (attributeTxt)
    {
        case "LastName":
           propertySelector = (person) => person.PrimaryName;
           break;
        case "FirstName":
           propertySelector = (person) => person.SecondaryName;
           break;
        ... etc

        default:
            // TODO: decide what to do with unknown attributeTxt
    }
}
string attributeTxt = ...
Expression<Func<Person, string>> propertySelector = attributeTxt.ToPropertySelector();
public static IQueryable<Person> Where(
    this IQueryable<Person> source,
    Expression<Func<Person, string>> propertySelector,
    OperatorValue operator,
    string value)
{
    // TODO: exceptions if incorrect parameters
    switch (operator)
    {
        case OperatorValue.Equals:
            return source.Where(item => propertySelector(item) == value);

        case OperatorValue.NotEquals:
            return source.Where(item => propertySelector(item) != value);

        case OperatorValue.StartsWith:
            return source.Where(item => propertySelector(item).StartsWith(value);

        case OperatorValue.Contains:
            return source.Where(item => propertySelector(item).Contains(value);

        default:
           // TODO
    }
}
IQueryable<Person> dataSet = db.Persons;
string attributeTxt = ...
string queryOperatorTxt = ...
string value = ...

Expression<Func<Person, string>> propertySelector = attributeTxt.ToPropertySelector();
OperatorValue operation = queryOperatorTxt.ToOperatorValue();

IQueryable<Person> queryPersons = dataSet.Where(propertySelector, operation);