web-dev-qa-db-fra.com

Comment puis-je implémenter des méthodes statiques sur une interface?

J'ai un tiers C++ DLL que j'appelle de C #.

Les méthodes sont statiques.

Je veux le résumer pour faire des tests unitaires. J'ai donc créé une interface avec les méthodes statiques qu'il contient, mais mon erreur de programme est maintenant liée à:

Le modificateur 'static' n'est pas valide pour cet élément

MyMethod cannot be accessed with an instance reference; qualify it with a type name instead

Comment puis-je atteindre cette abstraction?

Mon code ressemble à ceci

private IInterfaceWithStaticMethods MyInterface;

public MyClass(IInterfaceWithStaticMethods myInterface)
{
  this.MyInterface = myInterface;
}

public void MyMethod()
{
  MyInterface.StaticMethod();
}
72
Jon

Vous ne pouvez pas définir de membres statiques sur une interface en C #. Une interface est un contrat pour les instances.

Je recommanderais de créer l'interface telle que vous êtes actuellement, mais sans le mot clé static. Créez ensuite une classe StaticIInterface qui implémente l'interface et appelle les méthodes C++ statiques. Pour effectuer des tests unitaires, créez une autre classe FakeIInterface, qui implémente également l'interface, mais fait le nécessaire pour gérer vos tests unitaires.

Une fois que vous avez défini ces 2 classes, vous pouvez créer celle dont vous avez besoin pour votre environnement et la transmettre au constructeur de MyClass.

38
davisoa

Les interfaces ne peuvent pas avoir de membres statiques et les méthodes statiques ne peuvent pas être utilisées comme implémentation de méthodes d'interface.

Ce que vous pouvez faire est d'utiliser une implémentation d'interface explicite:

public interface IMyInterface
{
    void MyMethod();
}

public class MyClass : IMyInterface
{
    static void MyMethod()
    {
    }

    void IMyInterface.MyMethod()
    {
        MyClass.MyMethod();
    }
}

Sinon, vous pouvez simplement utiliser des méthodes non statiques, même si elles n'accèdent à aucun membre spécifique à une instance.

83
Danny Varod

Les membres statiques sont parfaitement légaux dans le CLR, mais pas le C #.

Vous pouvez implémenter un peu de colle dans IL pour relier les détails de la mise en œuvre.

Vous ne savez pas si le compilateur C # permettrait de les appeler?

Voir: 8.9.4 Définition du type d'interface ECMA-335.

Les types d'interface sont nécessairement incomplets puisqu'ils ne disent rien sur la représentation des valeurs du type d'interface. Pour cette raison, une définition de type d'interface ne fournira pas de définition de champ pour les valeurs du type d'interface (c'est-à-dire, les champs d'instance), bien qu'elle puisse déclarer des champs statiques (voir le § 8.4.3).

De même, une définition de type d'interface ne doit pas fournir d'implémentations pour des méthodes sur les valeurs de son type. Cependant, une définition de type d'interface peut définir - et définit généralement - des contrats de méthode (nom et signature de méthode) qui doivent être implémentés par les types pris en charge. Une définition de type d'interface peut définir et implémenter des méthodes statiques (voir le § 8.4.3) car les méthodes statiques sont associées au type d'interface lui-même plutôt qu'à une valeur du type.

16
leppie

Vous pouvez l'invoquer avec réflexion:

MyInterface.GetType().InvokeMember("StaticMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null);
5
John Koerner

Pourquoi ne pouvez-vous pas avoir de méthode statique sur une interface? Pourquoi C # n'autorise-t-il pas les méthodes statiques à implémenter une interface?

Cependant, je suggérerais de supprimer les méthodes statiques en faveur des méthodes d'instance. Si cela n'est pas possible, vous pouvez envelopper les appels de méthodes statiques à l'intérieur d'une méthode d'instance, puis créer une interface pour cela et exécuter vos tests unitaires à partir de cela.

c'est à dire

public static class MyStaticClass
{
    public static void MyStaticMethod()
    {...}
}

public interface IStaticWrapper
{
    void MyMethod();
}

public class MyClass : IStaticWrapper
{
    public void MyMethod()
    {
        MyStaticClass.MyStaticMethod();
    }
}
0
Justin Pihony