代码之家  ›  专栏  ›  技术社区  ›  Matt

使用LINQ和反射选择元数据

  •  0
  • Matt  · 技术社区  · 16 年前

    下面是这样的情况: 我正在尝试获取程序集中实现特定泛型接口的所有类型的集合,以及使用的泛型类型参数。我已经成功地组合了一个LINQ查询来执行这个操作,但是它看起来非常简化。

    I've read up on let and joins but couldn't see how to I'd use them to reduce the verbosity of this particular query. Can anyone provide any tips on how to shorten/enhance the query please?

    下面是一个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;
            }
        }
    }
    

    当做,

    马特

    1 回复  |  直到 16 年前
        1
  •  2
  •   Tomas Petricek    16 年前

    下面是一个示例,演示如何使用 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(); 
    

    这个 关键字的工作方式有点像变量声明,但它位于LINQ查询中—它允许您创建一个变量,该变量存储查询中稍后在多个位置需要的某些结果。您也提到了“join”,但它主要用于类似数据库的join(我不确定它在这里如何应用)。