c#4.0-创建具有子类型限制的linq表达式



我有一个类型为IEnumerable<MyBaseType>的列表,我正试图为它创建一个额外的where子句来检索列表中的特定项。特定值仅存在于子类型MyFirstType和MySecondType上。不在MyBaseType上。

有可能创造一种表达方式。。。

MyList.Where(b => (b is MyFirstType || (b is MySecondType)) && b.SpecificValue == message.SpecificValue);

以上不起作用,因为b的类型是MyBaseType,并且那里不存在SpecificValue。还要注意,我确实有另一个子类型MyThirdType,它都没有SpecificValue。

做我想做的事的作用是。。。

foreach (dynamic u in MyList)
{
    if (u is MyFirstType || u is MySecondType)
    {
        if (u.SpecificValue == message.SpecificValue)
        {
            //Extracted code goes here
            break;
        }
    }
}

有人知道如何为上述场景创建linq表达式吗?

也许有更好的解决方案,但在我看来,这可能足够好。。。如果你不介意表演。

那么,首先声明一个接口:

public interface IMySpecialType
{
   object SpecificValue {get; set;} //you didn't specify what type this is
   //all your other relevant properties which first and second types have in common
}

然后,使MyFirstType和MySecondType从这个接口派生:

public class MyFirstType : MyBaseType, IMySpecialType
{
   //snipet
}
public class MyFirstType : MySecondType, IMySpecialType
{
   //snipet
}

然后,过滤和铸造:

MyList
    .Where(b => (b is MyFirstType) || (b is MySecondType))
    .Cast<IMySpecialType>()
    .Where(b => b.SpecificValue == message.SpecificValue);
    //do something

将代码直接翻译为Linq where子句是

string messageValue = "foo";
var result = baseList.Where(item =>
{
    dynamic c = item;
    if(item is MyFirstType || item is MySecondType)
    {
        if( c.SpecificValue == messageValue)
            return true;
    }
    return false;
});

这将需要通过使用dynamic测试类的类型,因此您还可以直接将项强制转换为MyFirstTypeMySecondType

另一种选择是使用反射来检查该属性是否存在,使用这种方法,只要物品确实具有您感兴趣的属性,您就不依赖于物品的实际类型:

string messageValue = "foo";
var result = baseList.Where( item => 
    {
        var prop =  item.GetType().GetProperty("SpecificValue");
        if (prop != null && prop.GetValue(item, null) == messageValue)
            return true;
        else return false;
    });

如果修改类层次结构是一个选项,您可以让MyFirstTypeMySecondType实现一个包含属性的接口,那么您可以在Linq查询中使用OfType()

interface ISpecific
{
    string SpecificValue { get; set; }
}
class MyFirstType : MyBase, ISpecific
{
    public string SpecificValue { get; set; }
}
...
string messageValue = "foo";
var result = baseList.OfType<ISpecific>()
                     .Where(item => item.SpecificValue == messageValue);

一种更简单的方法是创建一个接口来标记所有具有此属性的类SpecificValue。然后是儿童游戏:

    static void Main(string[] args)
    {
        List<MyBaseType> MyList = new List<MyBaseType>();
        ISpecificValue message = new MyFirstType();
        MyList.OfType<ISpecificValue>().Where(b => b.SpecificValue == message.SpecificValue);
    }
}
class MyBaseType { }
interface ISpecificValue { string SpecificValue { get; set; } }
class MyFirstType : MyBaseType, ISpecificValue
{
    public string SpecificValue;
}
class MySecondType : MyBaseType, ISpecificValue
{
    public string SpecificValue;
}

相关内容

  • 没有找到相关文章

最新更新