我有一个类型为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测试类的类型,因此您还可以直接将项强制转换为MyFirstType
或MySecondType
。
另一种选择是使用反射来检查该属性是否存在,使用这种方法,只要物品确实具有您感兴趣的属性,您就不依赖于物品的实际类型:
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;
});
如果修改类层次结构是一个选项,您可以让MyFirstType
或MySecondType
实现一个包含属性的接口,那么您可以在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;
}