在C#中创建一个接口的实例

9

我正在使用C#中的接口,是否可以创建一个实现该接口的对象而不是编写完全新的实现该接口的类?该接口定义如下:

public interface ITokenStore
{

    IToken CreateRequestToken(IOAuthContext context);


    IToken CreateAccessToken(IOAuthContext context);
}

我知道在Java中我可以做类似以下的事情:
ITokenStore tokenStore = new ITokenStore()
    {
        IToken CreateRequestToken(IOAuthContext context) {
            IToken requestToken = null;

            return requestToken;
        }

        IToken CreateAccessToken(IOAuthToken context) {
            IToken accessToken = null;

            return accessToken;
        }
    };

有没有一种在C#中实例化接口的等效方法?

2
Java仍然在后台创建一个类,它只是一种语法糖的形式 - 在某种程度上,这是他们对缺少委托/函数指针的解决方案。 - Dai
1
使用模拟框架,您可以创建一个实例,例如 new Mock<ITokenStore>()。您可能希望设置具体方法的实现,这些方法可能来自委托。 - Jeppe Stig Nielsen
可能是重复的问题:这个问题有没有C#的等价物? - nawfal
7个回答

13

在C#中,“创建接口实例”的唯一方法是创建实现该接口的类型的实例。


它将被编译为匿名类。 - Sriram Sakthivel
7
不,你不能在.NET/C#中这样做,而且要明确,Java也不能这样做。Java编译器所做的是为您构建匿名类型,实现接口的类型。因此,Java有一种获取该类型的快捷方式,而C#没有。 - Lasse V. Karlsen
虽然 C# 或许不能,但是微软的 C# 编译器却可以:请见下面 oakio 的回答。只是它不是任何规范的一部分(而且使用受到极大限制),所以使用它真的不是一个好主意。 - Michael

4
如果您真的想要这个:
    private static void Main(string[] args)
    {
        IFoo foo = new IFoo(); // <- interface
        foo.Print();

        Console.ReadKey();
    }


    [ComImport, Guid("A7D5E89D-8FBD-44B7-A300-21FAB4833C00"), CoClass(typeof(Foo))]
    public interface IFoo
    {
        void Print();
    }

    public class Foo : IFoo
    {
        public void Print()
        {
            Console.WriteLine("Hello!");
        }
    }

但是,如果你在ildasm.exe上打开编译后的程序集,你会看到:

IL_0001: newobj instance void TestApp.Program/Foo::.ctor()


4

接口在设计时本身就没有逻辑。它们只是实际上什么也不做。

如果没有实现类,实例化接口甚至没有意义。


2
据我所知,.NET没有Java中匿名内部类的概念。在单元测试场景中,通常需要动态实现接口。因此,你可以尝试使用一些动态模拟框架,比如:
  1. Impromptu Interface(包括对dynamic的支持)
  2. Moq
请在NuGet gallery上查找标记为mocking的软件包。

0

类似这样的东西:

public class MyTokenStore: ITokenStore
{
    public IToken CreateRequestToken(IOAuthContext context)
    {
        ...some code here...
    }
    public IToken CreateAccessToken(IOAuthContext context)
    {
        ...some code here...
    }
}

然后使用它:
ITokenStore x = new MyTokenStore();

0

像其他人所说,不,这是不可能的。

但是,您可以编写一个通用类,该类具有每个方法的委托。类似以下内容:

public class DelegateTokenStore : ITokenStore
{
    public delegate IToken TokenCreator(IOAuthContext context);
    public TokenCreator RequestTokenCreator { get; set; }
    public TokenCreator AccessTokenCreator { get; set; }

    public IToken CreateRequestToken(IOAuthContext context)
    {
        return RequestTokenCreator(context);
    }

    public IToken CreateAccessToken(IOAuthContext context)
    {
        return AccessTokenCreator(context);
    }
}

然后你可以像这样使用它:

ITokenStore tokenStore = new DelegateTokenStore()
{
    RequestTokenCreator = (context) =>
    {
        IToken requestToken = null;
        return requestToken;
    },
    AccessTokenCreator = (context) =>
    {
        IToken accessToken = null;
        return accessToken;
    },
};

我并不是说采用这种方法一定是个好主意。就像任何事情一样,适用性取决于你的使用情况。


0

在C#中,您无法创建接口的实例。您必须创建实现该接口的类/类型的实例。

可能需要阅读一下C#中的接口。没有办法像Java那样“伪造”它。

我对这个概念很感兴趣,因为它是另一种语言中可用的东西。我想,如果您的使用者知道如何伪造鸭子类型,则可以使用带有委托参数的匿名类。但那几乎不值得。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接