【问题标题】:How to use LINQ to query a [key] property using generic types?如何使用 LINQ 使用泛型类型查询 [key] 属性?
【发布时间】:2019-11-07 05:10:06
【问题描述】:

假设我有一堂课:

public class Customer
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
}

现在我想创建一个通用的Get() 方法,它可以查询Customer 或其他几个定义了[key] 字段的类中的任何一个。

public T Get<T>(int id)
{            
    string json = DoSomething(); // <-- making it easy for this post
    List<T> items = JsonConvert.DeserializeObject<List<T>>(json);            
    return items.FirstOrDefault(i => i. ????? = id);
}

我不确定如何使用 Linq 一般指定 [key] 字段。

谢谢!

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    希望这会有所帮助:

    public interface IBase
    {
        int Id { get; }
    }
    public class Customer : IBase
    {
        public string Name { get; set; }
        public int Id { get ; set ; }
    }
    public T Get<T>(int id) where T : IBase
    {
        string json = DoSomething(); // <-- making it easy for this post
        List<T> items = JsonConvert.DeserializeObject<List<T>>(json);
        return items.FirstOrDefault(i => i.Id == id);
    }
    

    只需在所有其他类中实现接口IBase

    【讨论】:

    • 不客气。如果有效,请将其标记为正确。 :)
    • 我总是这样! (只需进行一项编辑:(i =&gt; i.Id == id)
    • @CaseyCrookston - 做到了
    • 这个答案不符合原帖的标准。它说“还定义了一个 [key] 字段”,而这篇文章只为特定接口添加了一个约束。我建议 OP 编辑​​他的问题以反映他需要知道的内容......
    • @Areks,如果您想发布符合我的 OP 的答案,我会非常乐意考虑。
    【解决方案2】:

    我认为使用合约是解决这个问题的更好方法。但是,如果您或其他人确实需要检查属性,这就是答案:

    public static T Get<T>(int id)
    {
        string json = DoSomething(); // <-- making it easy for this post
        List<T> items = JsonConvert.DeserializeObject<List<T>>(json);
    
        return items.FirstOrDefault(
            item => (int)item.GetType()
                             .GetProperties()
                             .FirstOrDefault(
                                p => Attribute.IsDefined(p, typeof(KeyAttribute))
                             ).GetValue(item) == id
        );
    }
    

    就你问题的这一部分而言:

    我不确定如何使用 Linq 一般指定 [key] 字段。

    属性是KeyAttribute,您可以通过导航到定义了解这一点(如果您正在使用 VS,请按 F12 或检查文档以防您的编辑器不支持此功能。

    需要考虑的事项:

    • 这是合理地大量使用反射,所以它永远不会有最好的性能。话虽如此,您可以在某处缓存来自 GetProperties() 的结果,以便更快地查找。
    • 它将演员阵容硬编码为int,但看起来这就是您所追求的。
    • 如果集合为 null,则会引发异常。

    【讨论】:

    • 所以你会反思每一个查询?仅使用命名约定时,您可以获得编译时优势,Id 属性通常是 Key 属性。无论如何,很明显这个问题需要一个编译时解决方案。 stackoverflow.com/questions/26521670/… - 顺便说一句,任何地方都有NO CAST
    • 是的。每次调用该方法时,它当然会使用反射。该问题要求存在一个属性,目前无法在编译时完成。在 return 语句中还有一个演员表。
    • There is no castGet 方法中的参数本身是int。仔细看。
    • 那你怎么称呼它? (int)item.GetType().....?仔细查看 (int) 部分。
    • 我的意思是不需要演员表。 class Class1 : IBase { public int Id { get; } void meth() { Get&lt;Class1&gt;(1); }
    猜你喜欢
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    • 2017-12-31
    • 2016-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多