2012-09-17 10 views
10

En algún método de clase, A, necesito llamar a un método de biblioteca B, que toma como IProgress<Object> como parámetro.C# ¿Es posible suministrar una lambda cuando se requiere una interfaz?

Normalmente, podría implementar IProgress<Object> como parte de la clase donde reside A, y luego pasar "esto" al método B. O tal vez podría crear una nueva clase cuyo único propósito es implementar IProgress<Object> y manejarlo correctamente-- entonces en este caso crearía una instancia de esa clase y la pasaría a B.

Pero lo que realmente quiero es que mi implementación de IProgress<Object> aparezca dentro del método en el que llamo B, entonces que hay menos desconexión visual entre el código de llamada y la implementación IProgress<Object>. (Considero que mi implementación de IProgress es una especie de detalle privado y no compartido del método de llamada y, por lo tanto, no quiero que mi implementación de IProgress<Object> esté en un método completamente separado de tal vez una clase completamente distinta).

Lo que he estado tratando de hacer es usar una lambda en la que definiré mi corta el progreso manipulación, y entonces de alguna manera pasar este lambda a B, de esta manera:

method in class A { 
... 
Action<Object> Report = (m) => { // do something useful with m }; 

B(Report) 
} 

method B(IProgress<Object> reporter) { 
    reporter.Report(some object) 
} 

Por supuesto, sé por qué esto no funcionará como está: B quiere un objeto que implementa IProgress<Object> y en su lugar le entrego un objeto de Acción.

¿Hay alguna manera de lograr lo que estoy tratando de lograr? (Es decir, tener mi aplicación si IProgress<Object> aparecer dentro método A?

+2

C# lambdas son delegados anónimos . Lo que necesitas es un tipo anónimo que implemente la interfaz. Consulte [esta pregunta] (http://stackoverflow.com/questions/191013/can-a-c-sharp-anonymous-class-implement-an-interface) para obtener algunas soluciones sobre los tipos anónimos de propiedades únicas que proporciona C#. –

Respuesta

11

Los delegados no pueden implementar interfaces (directamente).

Dos buenas opciones vienen a la mente:

  1. cambiar la definición del método que está llamando a tomar unos tipos delegado en lugar de un tipo IProgress. (De ser posible, esta sería la opción preferible)

  2. Cree un nuevo tipo que implemente la interfaz que necesita y tome un delegado como parámetro para implementar esa funcionalidad.

y el ejemplo de # 2, mientras que depende de la interfaz, podría ser algo como esto:

interface IProgress<T> 
{ 
    void doStuff(T param); 
} 

class LambdaProgress<T> : IProgress<T> 
{ 
    Action<T> action; 
    public LambdaProgress(Action<T> action) 
    { 
     this.action = action; 
    } 

    public void doStuff(T param) 
    { 
     action(param); 
    } 
} 

entonces sería capaz de hacer algo como:

B(new LambdaProgress<Object>(obj => ...)); 
1

Suponiendo que su interfaz IProgress<object> tiene sólo el único método void Report(object), y que el control de la API, podría simplemente redefinir los métodos que actualmente requieren un parámetro de tipo IProgress<object> a en cambio requiere un nuevo tipo de delegado:

public delegate void ProgressReportDelegate(object someObject); 

Luego, su ejemplo podría cambiar a:

method in class A { 
... 
Action<Object> Report = (m) => { // do something useful with m }; 

B(Report) 
} 

method B(ProgressReportDelegate reporter) { 
    reporter(someObject); 
} 

para las interfaces más complejas, o donde no controlas la API (y por lo tanto no puedes cambiar un método para llevar al delegado en lugar de al objeto que implementa esa interfaz), esta no es realmente una opción, pero parece funcionar en tu caso.

4

No, no puedes suministrar un lambda cuando se requiere una interfaz.
Pero puede suministrar un objeto anónimo utilizando impromptu-interface.

Este ejemplo es de la página del proyecto:

//Anonymous Class 
var anon = new 
{ 
    Prop1 = "Test", 
    Prop2 = 42L, 
    Prop3 = Guid.NewGuid(), 
    Meth1 = Return<bool>.Arguments<int>(it => it > 5) 
} 

var myInterface = anon.ActLike<IMyInterface>(); 

En el ejemplo, esto puede ser:

A 
{ 
    // Create an anonymous object. 
    var anonymous = new 
    { 
     // Define a method that needs an "object" parameter and returns nothing. 
     Report = Return.Arguments<object>(m => 
     { 
      // Do whatever you want to do when Report is called. 
     }) 
    } 

    // Get your anonymous object as an IProgress<Object>. 
    var obj = anonymous.ActLike<IProgress<Object>> 

    // Call B. 
    B(obj); 
} 
0

Con .NET 4.5 se puede utilizar Progress clase

Cuestiones relacionadas