情况如下: 我正在尝试获取程序集中所有类型的集合,这些集合实现了特定的通用接口以及使用的泛型类型参数。我已经设法将一个Linq查询放在一起执行此操作,但它似乎非常冗长。
我已经阅读了let和join,但看不清楚如何使用它们来减少此特定查询的详细程度。任何人都可以提供有关如何缩短/增强查询的任何提示吗?
这是一个MSTest类,它当前通过并演示了我想要实现的目标:
[TestClass]
public class Sample
{
[TestMethod]
public void MyTest()
{
var results =
(from type in Assembly.GetExecutingAssembly().GetTypes()
where type.GetInterfaces().Any(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(MyInterface<,>)
)
select new ResultObj(type,
type.GetInterfaces().First(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(MyInterface<,>)
).GetGenericArguments()[0],
type.GetInterfaces().First(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(MyInterface<,>)
).GetGenericArguments()[1]
)).ToList();
Assert.AreEqual(1, results.Count);
Assert.AreEqual(typeof(int), results[0].ArgA);
Assert.AreEqual(typeof(string), results[0].ArgB);
}
interface MyInterface<Ta, Tb>
{ }
class MyClassA : MyInterface<int, string>
{ }
class ResultObj
{
public Type Type { get; set; }
public Type ArgA { get; set; }
public Type ArgB { get; set; }
public ResultObj(Type type, Type argA, Type argB)
{
Type = type;
ArgA = argA;
ArgB = argB;
}
}
}
此致
马特
答案 0 :(得分:2)
以下是一个示例,说明如何使用let
关键字重写此内容:
var results =
(from type in Assembly.GetExecutingAssembly().GetTypes()
// Try to find first such interface and assign the result to 'ifc'
// Note: we use 'FirstOrDefault', so if it is not found, 'ifc' will be null
let ifc = type.GetInterfaces().FirstOrDefault(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(MyInterface<,>))
// Filtering and projection can now use 'ifc' that we already have
where ifc != null
// Similarly to avoid multiple calls to 'GetGenericArguments'
let args = ifc.GetGenericArguments()
select new ResultObj(type, args[0], args[1])).ToList();
let
关键字有点像变量声明,但它存在于LINQ查询中 - 它允许您创建一个变量,该变量存储查询后面多个位置所需的结果。你也提到了“连接”,但这主要用于类似数据库的连接(我不确定它在这里是如何应用的)。