【问题标题】:LINQ query on object with unknown class对具有未知类的对象的 LINQ 查询
【发布时间】:2011-08-24 16:21:16
【问题描述】:

我有一个未知(对于当前方法)类对象的数组。我知道每个类都有一个名为“Number”的属性。 我正在尝试编写一个 LINQ 查询,在其中查找具有下一个数字的对象。 AKA,我在 8 号,使用 LINQ 查询查找 Number=9 的对象。

有人有建议吗?

另外,我经常使用反射,所以不用担心会避免它。

【问题讨论】:

  • 你怎么知道每个对象都有一个 Number 属性?他们是匿名课程吗?它们是您可以转换为的已知类型吗?它们都是同一类型吗?
  • 它们可以是任何类类型。我确实知道它们都有一个 Number 属性,因为我是这样设计它们的。
  • 如果您将所有类都设计为具有表示某种含义的 Number 属性,但没有在接口中捕获该含义,那么您可能需要考虑更改您的设计。您的问题最好用“所有具有 Number 属性的类都实现一个通用接口,因为您以这种方式设计它们”来回答。

标签: c# vb.net linq reflection .net-3.5


【解决方案1】:

如果您确实没有可以简化为的通用类型,并且由于某种原因无法引入这种类型,那么您可以使用动态关键字。我目前无法访问编译器,但是您的方法可以接受动态对象的集合并查询它们吗?

例如:

IEnumerable<dynamic> collection = ...;
var numbers = from x in collection
              select x.Number;

【讨论】:

  • 我们刚刚升级到 .NET 3.5,由于购买了 Visual Studio 许可证和增加的 v4 框架大小,我们无法升级到 .NET 4 Framework
  • @Craig:框架大小有什么问题?快点!!现在是 2011 年,没有人应该关心额外的 12 mb
  • 这是一个侧面。主要问题是我们最近才购买了一些 Visual Studio 2008。
【解决方案2】:

如果您在其他地方指出您设计了所有类,那么您可以将该数字属性放在一个 in 接口中,并让所有类实现该接口。然后,在 linq 查询中,使用接口。

【讨论】:

  • 忘记了接口...会调查它。也许是可能的。同时我还是会接受别人的想法。
  • @phoog,你打败了我。我已经发布了类似的解决方案:)
  • 我有一个附带问题,我的一个类有一个名称稍有不同的属性。如何将接口“Number”属性指向该特定类的“Index”属性?
  • 给有问题的类一个数字属性,它只返回索引属性。我可能会将新属性设为显式实现。
  • @Craig,您可以通过说class MyClass : IHasNumber { int IHasNumber.Number { get { return SomeOtherProperty; } } } 来使用显式接口实现。这将使该类实现 IHasNumber,但仅当您将其视为 IHasNumber 时才会显示该属性。另外,考虑在单独的问题中提出这个问题,以便人们可以在 cmets 之外回答:)
【解决方案3】:

您可以使用属性 Number 创建一个接口 - INumber。数组中的每个对象都可以实现这个接口。

这样,您将拥有一个已知类型 INumber 的数组。这样您的查询将易于调试和维护。

【讨论】:

  • phoog 打败了我。他发布了类似的解决方案:)。
【解决方案4】:

如果对象都继承自已知接口,那么您可以强制转换它们,例如

var next = items.Cast<IHasNumber>.FirstOrDefault(x => x.Number == index + 1);

如果他们不这样做,那么您可以使用dynamic,例如

var next = items.Cast<dynamic>.FirstOrDefault(x => x.Number == index + 1);

如果您可以控制类型,那么我会让它们实现一个接口,以便您可以使用第一种方法,这应该比第二种方法快得多。在这种情况下,您的收藏可能会从 IEnumerable&lt;IHasNumber&gt; 开始,您甚至不必投射。

【讨论】:

    【解决方案5】:

    为避免性能问题,您可以使用以下方法:

    static void Main(string[] args)
    {
        object[] objs = GetInitialData();
    
        var accessor = GetGetterHelper<int>(objs[0].GetType(), "Number");
    
        var res = from a in objs where accessor(a) == 7 select a;
    
    }
    
    static Func<object, T> GetGetterHelper<T>(Type type, string methodName)
    {
        var methodInfo = type.GetProperty(methodName).GetGetMethod();
    
        return x => (T)methodInfo.Invoke(x, new object[] {});
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-08
      • 2022-01-25
      • 2014-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多