2012-02-23 15 views
41

Tengo una DLL de C++ de terceros a la que llamo desde C#.¿Cómo puedo implementar métodos estáticos en una interfaz?

Los métodos son estáticos.

Quiero abstracta hacia fuera para hacer algunas pruebas unitarias así que creé una interfaz con los métodos estáticos en ella, pero ahora mis errores del programa con:

El modificador 'estático' no es válido para este artículo

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

¿Cómo puedo lograr esta abstracción?

Mi código es el siguiente

private IInterfaceWithStaticMethods MyInterface; 

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

public void MyMethod() 
{ 
    MyInterface.StaticMethod(); 
} 
+1

Tal vez usted puede hacerlo con los métodos de extensión: http://stackoverflow.com/questions/1243921/c-sharp-interface-static-method-call-with-generics – hcb

Respuesta

20

No se puede definir miembros estáticos en una interfaz en C#. Una interfaz es un contrato, no una implementación.

Recomendaría crear la interfaz como lo está actualmente, pero sin la palabra clave estática. A continuación, cree una clase StaticIInterface que implemente la interfaz y llame a los métodos estáticos de C++. Para realizar pruebas unitarias, cree otra clase FakeIInterface, que también implemente la interfaz, pero que haga lo que necesita para manejar las pruebas de su unidad.

Una vez que haya definido estas 2 clases, puede crear la que necesita para su entorno y pasarla al constructor MyClass.

+36

-1 por decir 'Una interfaz es un contrato, no una implementación. - eso es cierto, pero completamente irrelevante (* non sequitur *) aquí, ya que * el método estático no es parte de la implementación en sí * - la implementación, por definición, se basa en * datos *, que es , a su vez, * inaccesible * para miembros estáticos. 'Una definición de tipo de interfaz puede definir e implementar métodos estáticos (ver §8.4.3) ya que los métodos estáticos están asociados con el tipo de interfaz en sí, más que con cualquier valor del tipo. - tenga en cuenta que los miembros 'estáticos' suelen ser * métodos de utilidad *. – vaxquis

+0

entiendo y estoy de acuerdo con sus estados de cuenta, y me siento su comentario es importante contexto también. A pesar de que. Al diseñar una interfaz, uno debe considerarla como un contrato, lo que implica que los métodos estáticos no se aplican. Pensé que debería dejarlo allí para ayudar a algunas personas a entender el propósito de una interfaz. ¿La comunidad siente que debería eliminarse? – davisoa

+0

I parcialmente de acuerdo en que 'Una interfaz es un contrato, no un implementation' es inútil, a veces un poco contextualización realmente ayuda. Y estoy totalmente de acuerdo con el método estático 'no es una parte de la aplicación en sí ', los métodos estáticos ** ** han una implementación, se convierten en parte de la aplicación sólo si se utiliza como aplicación en la ejecución de cualquier otro método. Sin embargo, mi diccionario se basa en lo aprendido, hasta donde yo sé, la terminología realmente varía también dependiendo del lenguaje de programación. Los métodos estáticos no pueden ser interfaces porque de todos modos solo puede haber 1 implementación. Imagínese – GameDeveloper

50

Las interfaces no pueden tener miembros estáticos y los métodos estáticos no se pueden usar como implementación de métodos de interfaz.

Lo que puede hacer es usar una implementación de interfaz explícita:

public interface IMyInterface 
{ 
    void MyMethod(); 
} 

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

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

Como alternativa, puede simplemente utilizar métodos no estáticos, incluso si no tienen acceso a cualquier instancia de miembros específicos.

+0

Para cualquiera que se pregunte por qué alguien querría hacer esto, es particularmente útil al escribir pruebas de unidad/integración para código heredado que implementa métodos estáticos. – Dezzamondo

0

cuanto a por qué no se puede tener un método estático en una interfaz: Why Doesn't C# Allow Static Methods to Implement an Interface?

Sin embargo, sugeriría la eliminación de los métodos estáticos en favor de los métodos de instancia. Si eso no es posible, puede envolver las llamadas al método estático dentro de un método de instancia, y luego puede crear una interfaz para eso y ejecutar las pruebas de su unidad a partir de eso.

es decir

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

public interface IStaticWrapper 
{ 
    void MyMethod(); 
} 

public class MyClass : IStaticWrapper 
{ 
    public void MyMethod() 
    { 
     MyStaticClass.MyStaticMethod(); 
    } 
} 
5

Se podría invocar con la reflexión:

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

Y si no tiene una instancia de MyInterface puede usar "typeOf (MyInterface)" en lugar de "myInterface.GetType()". – RenniePet

+0

Parecía una buena idea en ese momento, y puedo continuar haciéndolo mediante la reflexión, pero una pequeña advertencia: se vuelve más problemático si el programa se ofusca de modo que el método StaticMethod se renombra. – RenniePet

+0

@RenniePet: En su lugar, podría tratar parcialmente el cambio de nombre de StaticMethod usando nameof (StaticMethod). PODRÍA ayudar con un ofuscador dependiendo de cómo cambia el nombre.Si lo haces de esta forma, al menos verías un error de tiempo de compilación. –

11

miembros estáticos son perfectamente legal en el CLR, simplemente no C#.

Puede implementar algo de pegamento en IL para vincular los detalles de implementación.

¿No está seguro si el compilador C# permitiría llamarlos?

Ver: 8.9.4 Definición del tipo de interfaz ECMA-335.

Los tipos de interfaz son necesariamente incompletos ya que no dicen nada sobre la representación de los valores del tipo de interfaz. Por esta razón , una definición de tipo de interfaz no proporcionará campo definiciones para valores del tipo de interfaz (es decir, campos de instancia), aunque puede declarar campos estáticos (véase §8.4.3).

Del mismo modo, una definición de tipo de interfaz no deberá proporcionar implementaciones para cualquiera de los métodos en los valores de su tipo. Sin embargo, una definición de tipo interfaz puede-y por lo general no-definir contratos método (nombre del método y firma del método) que serán ejecutadas por tipos de apoyo. Un tipo de definición de interfaz puede definir y implementar métodos estáticos (véase §8.4.3) ya que los métodos estáticos son asociado con el mismo tipo de interfaz en lugar de con cualquier valor del tipo.

+7

Como referencia, 'CLS Rule 19: las interfaces que cumplen con CLS no deben definir métodos estáticos ni definir campos. 'Continúa diciendo que está bien que los consumidores que cumplen con CLS rechacen estos tipos de interfaces. Hace un año intenté llamar a un método estático en una interfaz y el compilador de C# no compilaría. –

+0

Además de @ChristopherCurrens nota sobre el CLS: 'Common Language Specification (CLS) es un conjunto de características básicas del lenguaje que se necesitan .Net Languages ​​.... Cuando hay una situación para comunicar objetos escritos en diferentes .Net Quejas de idiomas, aquellos los objetos deben exponer las características que son comunes a todos los lenguajes. Tiene sentido que si el CLS trata sobre la interoperabilidad entre diferentes lenguajes .NET, y C# no permite miembros estáticos en una interfaz, entonces el CLS también los prohibiría. , para asegurar que las bibliotecas en otros lenguajes .NET puedan ser llamadas desde C#. –

Cuestiones relacionadas