2010-07-17 93 views
27

c#中有一些黑魔法代码,您可以在其中定义接口的默认实现。如何在c#中定义接口的默认实现?

所以,你可以写

var instance = new ISomeInterface(); 

任何指针?

更新1:请注意,我没有问是否这是一个好主意。怎么可能做到这一点。

更新2:给任何人看到接受的答案。

  • “这应该只被视为一种好奇心。”来自Marc Gravel "Newing up" Interfaces
  • “使用为COM互操作设计的工具完全和完全不同,这是一个糟糕的主意,这会让你的代码无法理解下一个必须维护它的人”Eric Lippert "Newing up" Interfaces
  • “虽然它可能有效,但如果它是由有理编码器在生产代码中发现的,它将被重构为使用基类或依赖注入。”来自Stephen Cleary在下面的评论。
+0

一些这方面的文章:HTTP://计算器。 com/questions/1093536 and http://blogs.msdn.com/b/ericlippert/archive/2007/04/20/chained-user-defined-explicit-conversions-in-c-part-three.aspx – 2010-07-18 15:47:27

+0

Is there仍然没有理智的方式来做到这一点? – 2014-01-04 14:53:14

+0

@WilliamJockusch仍然是我认识的唯一一个 – Simon 2014-01-07 09:50:46

回答

28

这里来的黑魔法:

class Program 
{ 
    static void Main() 
    { 
     IFoo foo = new IFoo("black magic"); 
     foo.Bar(); 
    } 
} 

[ComImport] 
[Guid("C8AEBD72-8CAF-43B0-8507-FAB55C937E8A")] 
[CoClass(typeof(FooImpl))] 
public interface IFoo 
{ 
    void Bar(); 
} 

public class FooImpl : IFoo 
{ 
    private readonly string _text; 
    public FooImpl(string text) 
    { 
     _text = text; 
    } 

    public void Bar() 
    { 
     Console.WriteLine(_text); 
    } 
} 

注意,不仅可以实例化一个接口,但也将参数传递给它的构造:-)

+4

嗯,我确实说这是黑魔法。谢谢Darin。 – Simon 2010-07-17 11:48:56

+0

随着关键字“CoClass”的谷歌神与我同在。 http://ayende.com/Blog/archive/2009/08/15/instantiating-interfaces.aspx http://marcgravell.blogspot.com/2009/08/who-says-you-cant-instantiate-interface .html – Simon 2010-07-17 12:13:56

+0

@Simon,那些是两个博客我建议你将你的RSS阅读器调整为:-) – 2010-07-17 12:15:22

3

只有ISomeInterface是一类。

更新(澄清):

乔恩斯基特有a talk他提到的默认实现的接口。不过,它们不是C#语言的一部分。这个演讲是关于Jon Skeet会在未来版本的C#中看到

现在,唯一的默认实现是通过(可能是abstract)基类完成的。

+0

有人经历了所有理性的答案,并得出了... – 2010-07-17 11:53:48

+0

我低估了所有不正确的答案。因为它们不正确。没有理性。看Darins回答 – Simon 2010-07-17 12:05:36

+2

我看到了“正确的”答案。虽然它可能有效,但如果它是由有理编码器在生产代码中发现的,它将被重构为使用基类或依赖注入。 – 2010-07-17 12:22:10

2

也许你参考了依赖注入?当使用DI框架(如Ninject或Unity)时,您可以定义默认情况下为每个接口,然后用它是这样的:

(假设你有IWeapon接口和Sword实现它)

IKernel kernel = new StandardKernel(); 
kernel.Bind<IWeapon>().To<Sword>(); 
var weapon = kernel.Get<IWeapon>(); 

但Ninject(和大多数其他IoC框架)可以做一些更聪明的事情,比如:假设我们有类Warrior,它将IWeapon作为其构造函数中的参数。我们可以从Ninject得到Warrior一个实例:

var warrior = kernel.Get<Warrior>(); 

Ninject将通过我们指定的Warrior构造方法IWeapon实现并返回新的实例。

除此之外,我不知道任何允许这种行为的语言功能。

+0

好的建议,但不是我在找什么。 查看Darins答案 – Simon 2010-07-17 12:04:30

+1

是的,我错过了你提到的“黑魔法”的部分在你的问题:-) 谢谢你问 - 我学到了一些新东西! – arikfr 2010-07-17 12:27:35