2009-03-20 8 views
5

Próbuję utworzyć formularz, który będzie animował coś podczas przetwarzania określonego zadania (przekazywany jako delegat do konstruktora). Działa to dobrze, ale problem, który mam, polega na tym, że nie mogę utworzyć egzemplarza mojej klasy ogólnej, jeśli konkretna metoda, którą chcę wykonać, ma typ pustej przestrzeni.Podawanie pustej przestrzeni do ogólnej klasy

Rozumiem, że jest to zgodne z projektem i wszystkim, ale zastanawiam się, czy istnieje znane rozwiązanie tego typu sytuacji.

Jeśli to pomaga na wszystkich moich okien forma wygląda jak tak (przycięte na zwięzłość):

public partial class operatingWindow<T> : Form 
{ 
    public delegate T Operation(); 
    private Operation m_Operation; 

    private T m_ReturnValue; 
    public T ValueReturned { get { return m_ReturnValue; } } 

    public operatingWindow(Operation operation) { /*...*/ } 
} 

A ja nazywam się podoba:

operatingWindow<int> processing = new operatingWindow<int>(new operatingWindow<int>.Operation(this.doStuff)); 
processing.ShowDialog(); 

// ... 
private int doStuff() 
{ 
    Thread.Sleep(3000); 

    return 0; 
} 

Odpowiedz

4

Chciałbym nieco przemyśleć twój projekt.

Jeśli zaimplementowałeś przetwarzanie w klasie bazowej, możesz podklasować go 2 alternatywami, które byłyby prawie wymienne.

Pierwszy może być taki jak twój, gdzie wymaga operacji, która zwraca wartość. (Chciałbym przerobić to, aby użyć Func<T> zamiast mieć własny typ delegata, jednak:

Drugi może po prostu wykonać prostą akcję i nie podać wartości zwracanej. Oba mogą korzystać z tej samej procedury animacji/wyświetlania/itp. .. ale zapewnić inny sposób pracy można także przekazać ten off do innych metod wykorzystujących klasę bazową, która zapewni dużą elastyczność

Dzięki takiemu podejściu, można nazwać jak:

private void DoSleep() 
{ 
    Thread.CurrentThread.Sleep(5000); 
} 
private int ReturnSleep() 
{ 
    Thread.CurrentThread.Sleep(5000); 
    return 5000; 
} 
... 
{ 
    var actionWindow = new OperatingWindowAction(this.DoSleep); 
    actionWindow.Execute(); 
    var funcWindow = new OperatingWindowFunc<int>(this.ReturnSleep); 
    funcWindow.Execute(); 
    int result = funcWindow.Result; 
} 

Wyglądałoby to tak:

public abstract partial class OperatingWindowBase : Form 
{ 
    public void Execute() 
    { 
     // call this.OnExecute(); asyncronously so you can animate 
    } 
    protected abstract void OnExecute(); 
} 

public class OperatingWindowFunc<T> : OperatingWindowBase 
{ 
    Func<T> operation; 
    public T Result { get; private set; } 
    public OperatingWindowFunc<T>(Func<T> operation) 
    { 
     this.operation = operation; 
    } 
    protected override OnExecute() 
    { 
     this.Result = operation(); 
    } 
} 

public class OperatingWindowAction 
{ 
    Action operation; 
    public OperatingWindow(Action operation) 
    { 
     this.operation = operation; 
    } 
    protected override OnExecute() 
    { 
     operation(); 
    } 
} 
6

Nie, musisz utworzyć przeciążenie, aby to zrobić.

np.

public operatingWindow(Action action) 
{ 
    m_Operation=() => { action(); return null; } 
} 

Również nie trzeba zdefiniować własny delegata, można użyć Func<T> i działania.