Architecture 扩展方法用法-Isn';这不是个糟糕的设计吗?

Architecture 扩展方法用法-Isn';这不是个糟糕的设计吗?,architecture,.net-3.5,extension-methods,Architecture,.net 3.5,Extension Methods,我刚刚开始学习.NET3.5,如果以前有人问过这种问题,请原谅。我正在努力使用扩展方法,因为我刚刚下载了suteki shop的MVC电子商务产品。在这个项目中,有一个相当标准的存储库模式扩展了IRepository 为了扩展此接口公开的基本功能,使用了扩展方法,即: public static class CategoryRepositoryExtensions { public static Category GetRootCategory(this IRepository<C

我刚刚开始学习.NET3.5,如果以前有人问过这种问题,请原谅。我正在努力使用扩展方法,因为我刚刚下载了suteki shop的MVC电子商务产品。在这个项目中,有一个相当标准的存储库模式扩展了IRepository

为了扩展此接口公开的基本功能,使用了扩展方法,即:

public static class CategoryRepositoryExtensions
{
    public static Category GetRootCategory(this IRepository<Category> categoryRepository)
    {
     return categoryRepository.GetById(1);
    }
}
公共静态类CategoryRepositoryExtensions
{
公共静态类别GetRootCategory(此IRepository类别Repository)
{
返回categoryRepository.GetById(1);
}
}
现在这一切都很好,但是接口,就我而言,充当实现它们的对象的契约

存储库已经接口的事实表明,有人试图采用数据层不可知的方法。这就是说,如果我要创建自己的数据层,我会对必须创建哪些扩展方法来确保满足实现存储库类的类的合同要求感到困惑

似乎创建IRepository然后进行扩展的旧方法可以更好地了解所需内容,例如

ICategoryRepoitory : IRepository<Category>
{
     Category GetRootCategory();
}
iCategoryReportory:IRepository { 类别GetRootCategory(); } 所以我想我的问题是,对其他人来说,这种扩展方法的使用似乎是错误的吗?若否,原因为何?我不应该为此抱怨吗

编辑:

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

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


那样的话,如果我要把它换成另一种机制,我就必须在那个程序集中创建一个类似的扩展方法

关键是,如果您已经适当地实现了所有的
IRepository
,那么您(作为数据层实现者)根本不需要知道根类别。对于此扩展方法的范围,假定任何类别存储库都有一个ID为1的根类别。这很可能是一个完全合理的假设,也是一个有用的假设:没有人必须构建派生类(这很可能是不切实际的-数据层可能有工厂等,这使得从实现中派生很困难)

现在,扩展方法只有在其范围适当时才适用——如果它位于一个名称空间(或密切相关的名称空间)中,在这个名称空间中,关于根类别的假设是有效的


我不认为“更老”的方法真的是一个扩展
IRepository
的接口-它将是一个采用
IRepository
的普通静态方法。这就是扩展方法让生活更愉快的地方。如果您真的想使用继承,那么现在也可以这样做。不幸的是,我们对您系统的体系结构了解不够,无法确定这一点。

这不是一回事。扩展方法是一种语法上的便利,仅此而已,而且肯定不是合同要求。您不能在自己的类上“实现”它们。对于上面的示例:

using CategoryRepositoryExtensions;
...
Category c = r.GetRootCategory();
与以下内容完全相同:

Category c = CategoryRepositoryExtensions.GetRootCategory(r);

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

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

让我们考虑2种情况:

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

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

如果您使用的是传统的/接口驱动的方法,那么您可能会尝试定义2个不同的接口。如果您使用扩展方法,您可以使用如下内容

情景1

<IEnumerable> orders1Enumerable = OrderRepository.GetAllOrders()
                                     .ContainingProductCode(x);
orders1Enumerable=OrderRepository.GetAllOrders() .包含产品代码(x); 情景2

<IEnumerable> orders2Enumerable = OrderRepository.GetAllOrders()
                                     .ContainingProductCode(x)
                                     .WithShippingZipCode(y);
orders2Enumerable=OrderRepository.GetAllOrders() .包含产品代码(x) .带shippingzipcode(y); 执行此操作时,框架会通过链接这些扩展方法动态创建适当的SQL


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


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

好的方面,我现在更清楚地看到了扩展方法的好处。为澄清干杯。