扩展接口模式 [英] Extension interface patterns

查看:199
本文介绍了扩展接口模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在.NET 3.5中新的扩展允许功能从接口拆分出来。

The new extensions in .Net 3.5 allow functionality to be split out from interfaces.

例如,在NET 2.0

For instance in .Net 2.0

public interface IHaveChildren {
    string ParentType { get; }
    int ParentId { get; }

    List<IChild> GetChildren()
}

能(3.5)变为:

Can (in 3.5) become:

public interface IHaveChildren {
    string ParentType { get; }
    int ParentId { get; }
}

public static class HaveChildrenExtension {
    public static List<IChild> GetChildren( this IHaveChildren ) {
        //logic to get children by parent type and id
        //shared for all classes implementing IHaveChildren 
    }
}

这对我来说似乎是许多接口,一个更好的机制。他们不再需要一个抽象基分享这个code和功能上code的工作原理相同。这可能使code更容易维护,更容易进行测试。

This seems to me to be a better mechanism for many interfaces. They no longer need an abstract base to share this code, and functionally the code works the same. This could make code more maintainable and easier to test.

唯一的缺点是,一个抽象的基地实现可以是虚拟的,但可以在周围的工作(将一个实例方法隐藏具有相同名称的扩展方法?会是混乱的code这样做?)

The only disadvantage being that an abstract bases implementation can be virtual, but can that be worked around (would an instance method hide an extension method with the same name? would it be confusing code to do so?)

任何其他原因不能经常使用这种模式?

Any other reasons not to regularly use this pattern?


澄清:

是的,我看到的扩展方法的趋势是结束了他们无处不在。我会特别小心有任何.Net的价值类型,而大量的同行评审(我认为只有一个,我们对字符串的 .SplitToDictionary() - 类似于 .Split()但服用键值分隔符太)

Yeah, I see the tendency with extension methods is to end up with them everywhere. I'd be particularly careful having any on .Net value types without a great deal of peer review (I think the only one we have on string is a .SplitToDictionary() - similar to .Split() but taking a key-value delimiter too)

我觉得有一个整体的最佳实践的争论那里; - )

I think there's a whole best practice debate there ;-)

(顺便说一句:DannySmurf,你下午听起来很吓人)

(Incidentally: DannySmurf, your PM sounds scary.)

我专门询问这里有关使用扩展方法,其中previously我们有接口的方法。

I'm specifically asking here about using extension methods where previously we had interface methods.


我试图避免大量的抽象基类的层次 - 实现这些车型大多已经在类有基类。我觉得这种模式可以更容易维护,减少过度耦合比增加进一步的对象层次。

I'm trying to avoid lots of levels of abstract base classes - the classes implementing these models mostly already have base classes. I think this model could be more maintainable and less overly-coupled than adding further object hierarchies.

这是什么MS都做了IEnumerable和IQueryable的LINQ的?

Is this what MS have done to IEnumerable and IQueryable for Linq?

推荐答案

我认为明智地使用扩展方法把接口上(抽象)基类更equatable位置。

I think the judicious use of extension methods put interfaces on a more equatable position with (abstract) base classes.


版本。一个优点基类有超过接口是,你可以很容易地在以后的版本中添加新的虚拟的成员,而加入成员接口将打破建成对旧版本的库的执行者。相反,需要与新成员的接口的新版本被创建,该库将必须解决或限制访问旧式的对象只能实现原来的界面。


Versioning. One advantage base classes have over interfaces is that you can easily add new virtual members in a later version, whereas adding members to an interface will break implementers built against the old version of the library. Instead, a new version of the interface with the new members needs to be created, and the library will have to work around or limit access to legacy objects only implementing the original interface.

作为一个具体的例子,一个库的第一个版本可能会定义一个接口,像这样:

As a concrete example, the first version of a library might define an interface like so:

public interface INode {
  INode Root { get; }
  List<INode> GetChildren( );
}

在该库已经发布,我们不能修改界面不打破现有用户。相反,在未来的版本中,我们需要定义一个新的界面上添加额外的functionalty:

Once the library has released, we cannot modify the interface without breaking current users. Instead, in the next release we would need to define a new interface to add additional functionalty:

public interface IChildNode : INode {
  INode Parent { get; }
}

不过,只有用户的新图书馆将能实现新的接口。为了与旧code的工作,我们需要适应旧的实现,它的扩展方法可以处理很好:

However, only users of the new library will be able to implement the new interface. In order to work with legacy code, we need to adapt the old implementation, which an extension method can handle nicely:

public static class NodeExtensions {
  public INode GetParent( this INode node ) {
    // If the node implements the new interface, call it directly.
    var childNode = node as IChildNode;
    if( !object.ReferenceEquals( childNode, null ) )
      return childNode.Parent;

    // Otherwise, fall back on a default implementation.
    return FindParent( node, node.Root );
  }
}

现在新图书馆的所有用户都可以把传统和现代的实现相同。

Now all users of the new library can treat both legacy and modern implementations identically.


过载。另一个领域扩展方法可能是有用的是提供重载接口的方法。你可能有一种方法用几个参数来控制其动作,其中仅第一个或两个是在90%的情况下,非常重要的。由于C#不容许参数设置默认值,用户要么每次调用完全参数化方法,或每实现必须实现琐碎重载为核心的方法。


Overloads. Another area where extension methods can be useful is in providing overloads for interface methods. You might have a method with several parameters to control its action, of which only the first one or two are important in the 90% case. Since C# does not allow setting default values for parameters, users either have to call the fully parameterized method every time, or every implementation must implement the trivial overloads for the core method.

而不是扩展方法可以用来提供琐碎超负荷的实现:

Instead extension methods can be used to provide the trivial overload implementations:

public interface ILongMethod {
  public bool LongMethod( string s, double d, int i, object o, ... );
}

...
public static LongMethodExtensions {
  public bool LongMethod( this ILongMethod lm, string s, double d ) {
    lm.LongMethod( s, d, 0, null );
  }
  ...
}


请注意,这两种情况下都写在由接口提供的操作而言,涉及琐碎或众所周知的默认的实现。这就是说,你只能从一个类继承一次,并有针对性地采用扩展方法可以提供一个有价值的方式来处理一些由基类提供了细微的界面缺乏的:)


Please note that both of these cases are written in terms of the operations provided by the interfaces, and involve trivial or well-known default implementations. That said, you can only inherit from a class once, and the targeted use of extension methods can provide a valuable way to deal with some of the niceties provided by base classes that interfaces lack :)

编辑:相关的职位由Joe达菲:<一href="http://www.bluebytesoftware.com/blog/2010/02/10/ExtensionMethodsAsDefaultInterfaceMethodImplementations.aspx">Extension方法作为默认接口方法实现

A related post by Joe Duffy: Extension methods as default interface method implementations

这篇关于扩展接口模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆