热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

扩展方法的用法-这不是一个糟糕的设计吗?-Extensionmethodsusage-Isn'tthisbaddesign?

Ihavejuststartedtolookat.NET3.5sopleaseforgivemeifthistypeofquestionhavebeenaske

I have just started to look at .NET 3.5 so please forgive me if this type of question have been asked before. I am struggling with a decent usage for extension methods, in that I have just downloaded suteki shop an MVC ecommerce offering. In this project there is a pretty standard Repository pattern that extends IRepository.

我刚刚开始研究.NET 3.5,如果之前已经提出这类问题,请原谅我。我正在努力使用扩展方法,因为我刚刚下载了suteki商店的MVC电子商务产品。在这个项目中,有一个非常标准的Repository模式,它扩展了IRepository。

In order to extend the basic functionality exposed by this interface, extention methods are used i.e.:

为了扩展该接口所暴露的基本功能,使用了扩展方法,即:

public static class CategoryRepositoryExtensions
{
    public static Category GetRootCategory(this IRepository categoryRepository)
    {
     return categoryRepository.GetById(1);
    }
}

Now this is all well and good, but Interfaces, as far as I am concerned act as contracts to the objects that implement them.

现在这一切都很好,但就我而言,Interfaces充当了实现它们的对象的契约。

The fact that the repository has been interfaced out suggests an attempt at a data layer agnostic approach. That said, if I were to create my own data layer I would be confused as to what extension methods I would have to create to ensure I have fulfilled the contractual requirement I have to the classes that implement my repository classes.

存储库已经接口的事实表明尝试采用数据层不可知的方法。也就是说,如果我要创建自己的数据层,我会对我必须创建的扩展方法感到困惑,以确保我已经完成了对实现我的存储库类的类的合同要求。

It seems that the older way of creating an IRepository and then extending that allows a much better visibility of what is required e.g.

似乎创建IRepository然后扩展的旧方法允许更好地查看所需的内容,例如,

ICategoryRepoitory : IRepository
{
     Category GetRootCategory();
}

So I guess my question is does this use of Extention methods seem wrong to anyone else? If not, why? Should I not be moaning about this?

所以我想我的问题是,对于其他人来说,使用Extention方法似乎是错误的吗?如果没有,为什么?我不应该抱怨这个吗?

EDIT:

The above example does seem to be a good example of why extention methods can be very helpful.

上面的例子似乎是一个很好的例子,说明为什么扩展方法可以非常有用。

I suppose my issue is if data access specific implementations were stuck in the extention method in the data access mechanisms assembly.

我想我的问题是,如果数据访问特定的实现被卡在数据访问机制程序集中的扩展方法中。

That way if I were to swap it out for another mechanism I would have to create a similar extention method in that assembly.

这样,如果我将其换成另一种机制,我将不得不在该程序集中创建一个类似的扩展方法。

4 个解决方案

#1


5  

The point is that if you've implemented all of IRepository appropriately, you (as the data layer implementor) don't have to know about root categories at all. For the scope of this extension method, it is assumed that any repository of categories will have a root category of ID 1. That may well be a perfectly reasonable assumption, and a useful one: no-one has to build a derived class (which may well be impractical - the data layer may have factories etc which make it tricky to derive from the implementations).

关键是如果你已经适当地实现了所有的IRepository ,你(作为数据层实现者)根本不必知道根类别。对于此扩展方法的范围,假设任何类别的存储库都将具有ID 1的根类别。这可能是一个非常合理的假设,并且是一个有用的假设:没有人必须构建派生类(其中可能是不切实际的 - 数据层可能有工厂等,这使得从实现派生出来很棘手)。

Now, the extension method is only applicable if its scope is appropriate - if it's in a namespace (or closely related one) where that assumption about root categories will be valid.

现在,扩展方法仅适用于其范围适当的情况 - 如果它位于命名空间(或密切相关的范围)中,其中关于根类别的假设将是有效的。

I don't think the "older" way would really be an interface extending IRepository - it would be a normal static method taking IRepository. That's where extension methods just make life more pleasant. If you really would have used inheritance instead, it may well be appropriate to do so now as well. Unfortunately we don't know enough about the architecture of your system to say that for sure.

我不认为“较旧”的方式实际上是扩展IRepository 的接口 - 它将是一个采用IRepository 的常规静态方法。这就是扩展方法让生活更愉快的地方。如果你真的会使用继承,那么现在也可以这样做。遗憾的是,我们对您系统的架构知之甚少。

#2


4  

Extension methods concept is just syntactic sugar as some authors call it. It makes the code more readable though less understandable. Ultimately extension methods are just static ones which are the heritage of the procedural paradigm. They make the code tightly-coupled and less cohesive, harder to test and reuse.

扩展方法概念只是一些作者所称的语法糖。它使代码更具可读性,但不太容易理解。最终,扩展方法只是静态方法,是程序范式的遗产。它们使代码紧密耦合,内聚力更低,更难以测试和重用。

I am biased against this tendency of the C# programming language. This feature is attractive but it doesn't bring any benefits, quite the contrary it increases the complexity of the code.

我对C#编程语言的这种倾向有偏见。此功能很有吸引力,但它没有带来任何好处,恰恰相反,它增加了代码的复杂性。

#3


1  

It's not the same thing. An extension method is a syntactic convenience, nothing more, and certainly not a contractual requirement. You don't "implement" them on your own classes. For your example above:

这不是一回事。扩展方法是一种语法上的便利,仅此而且当然不是合同要求。你不要在自己的课上“实施”它们。对于上面的例子:

using CategoryRepositoryExtensions;
...
Category c = r.GetRootCategory();

is exactly the same as:

与以下内容完全相同:

Category c = CategoryRepositoryExtensions.GetRootCategory(r);

and therefore there is no additional requirement on the implementer of the interface.

因此对接口的实现者没有额外的要求。

#4


0  

Yes in the example you mentioned it does seem counter-intuitive and the reason is because you are working with a single object at a single level. I find that extension methods are most useful when you are working with IQueryable / IEnumerable collections.

是的,在您提到的示例中,它看起来似乎是违反直觉的,原因是因为您在单个级别上处理单个对象。当您使用IQueryable / IEnumerable集合时,我发现扩展方法最有用。

For eg. lets consider 2 scenarios:

例如。让我们考虑两种情况:

  • Scenario 1: get list of all orders which contain product x

    场景1:获取包含产品x的所有订单的列表

  • Scenario 2: get list of all orders which contain product x and have been shipped to zipcode y

    场景2:获取包含产品x并已发送到zipcode y的所有订单的列表

If you were using the traditional/interface driven approach you might define 2 be tempted to define 2 different interfaces. If you use extension methods, you could use something like the following

如果您使用传统/接口驱动的方法,您可能会定义2被诱惑定义2个不同的接口。如果使用扩展方法,则可以使用以下内容

Scenario 1

 orders1Enumerable = OrderRepository.GetAllOrders()
                                     .ContainingProductCode(x);

Scenario 2

 orders2Enumerable = OrderRepository.GetAllOrders()
                                     .ContainingProductCode(x)
                                     .WithShippingZipCode(y);

When you do this, the framework creates the appropriate SQL on the fly by chaining these extension methods

执行此操作时,框架会通过链接这些扩展方法来动态创建适当的SQL

Hope this helps

希望这可以帮助


推荐阅读
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 深度学习中的Vision Transformer (ViT)详解
    本文详细介绍了深度学习中的Vision Transformer (ViT)方法。首先介绍了相关工作和ViT的基本原理,包括图像块嵌入、可学习的嵌入、位置嵌入和Transformer编码器等。接着讨论了ViT的张量维度变化、归纳偏置与混合架构、微调及更高分辨率等方面。最后给出了实验结果和相关代码的链接。本文的研究表明,对于CV任务,直接应用纯Transformer架构于图像块序列是可行的,无需依赖于卷积网络。 ... [详细]
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
author-avatar
闻雪儿1116_414
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有