2012-09-17 11 views
10

W pewnym metody klasy A, muszę wywołać metodę biblioteki B, która przyjmuje jako IProgress<Object> jako parametr.C# Czy jest możliwe podanie lambda, gdy wymagany jest interfejs?

Zwykle mogę wprowadzić IProgress<Object> jako część klasy, w której A rezyduje, a następnie przekazać "to" do metody B. A może mogę utworzyć nową klasę, której jedynym celem jest implementacja IProgress<Object> i poprawne jej przetwarzanie-- wtedy w tym przypadku utworzę instancję tej klasy i przekażę ją B.

Ale tak naprawdę chcę, aby moja implementacja IProgress<Object> pojawiła się bezpośrednio w metodzie, w której dzwonię B, więc że istnieje mniej wizualnego rozłączenia między kodem wywołującym a implementacją IProgress<Object>. (Uważam, że moja implementacja IProgress jest rodzajem prywatnego, niewspółużytkowanego szczegółu metody wywoływania, a tym samym nie chcę, aby moja implementacja IProgress<Object> była w osobnej metodzie prawdopodobnie całej innej klasy).

Co Próbowałem zrobić to użyć lambda, w którym będę definiować mój krótki postęp przenoszenia, a następnie w jakiś sposób przekazać tę lambda do B, jak to:

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

B(Report) 
} 

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

Oczywiście, wiem dlaczego to nie zadziała tak jak jest - B chce, aby obiekt implementował IProgress<Object>, a zamiast tego wręczam mu obiekt Akcji.

Czy istnieje jakiś sposób, aby osiągnąć to, co staram się osiągnąć? (IE mam wdrożenie jeśli IProgress<Object> pojawiają się wewnątrz metody A?

+2

C# lambda są anonimowe delegaci . Potrzebny jest anonimowy typ, który implementuje interfejs. Zobacz [to pytanie] (http://stackoverflow.com/questions/191013/can-a-c-sharp-anonymous-class-implement-an-interface) dla niektórych obejść nad anonimowymi typami tylko własności publicznej, które zapewnia C#. –

Odpowiedz

11

Delegaci nie mogą realizować interfejs (pośrednio).

dwie dobre opcje przychodzą na myśl:

  1. zmienić definicję metody, że dzwonisz do potrwać typy delegata zamiast typ IProgress. (Jeśli to możliwe, jest to opcja preferowana)

  2. Utwórz nowy typ, który implementuje wymagany interfejs i przyjmuje jako parametr parametr do implementacji tej funkcji.

i przykład nr 2, natomiast w zależności od interfejsu, może wyglądać mniej więcej tak:

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); 
    } 
} 

wtedy byłbyś w stanie zrobić coś takiego:

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

Zakładając, że interfejs IProgress<object> ma tylko jedną metodę void Report(object), i że można kontrolować API, można po prostu przedefiniować metody, które obecnie wymagają parametr typu IProgress<object> do zamiast wymagać nowego typu delegat:

public delegate void ProgressReportDelegate(object someObject); 

Wtedy twój przykład może zmienić się:

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

B(Report) 
} 

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

dla bardziej złożonych interfejsów, lub jeśli nie kontrolujesz interfejsu API (i nie można zmienić metody przyjmowania delegata, a nie obiektu implementującego ten interfejs), nie jest to naprawdę opcja, ale wydaje się działać w twoim przypadku.

4

Nie, nie możesz podać lambda, gdy wymagany jest interfejs.
Ale można dostarczyć anonimowy obiekt za pomocą impromptu-interface.

Ten przykład jest z jego strony projektu:

//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>(); 

W przykładzie może to być:

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); 
} 
Powiązane problemy