2009-03-20 4 views
5

Sto provando a creare un modulo che animerà qualcosa durante l'elaborazione di una determinata attività (passata come delegato al costruttore). Funziona bene, ma il problema che sto avendo è che non posso istanziare una copia della mia classe generica se il particolare metodo che voglio eseguire ha un tipo di ritorno di vuoto.passaggio vuoto a una classe generica

Capisco che questo è di progettazione e tutto, ma mi chiedo se c'è una soluzione nota per situazioni come questa.

Se aiuta a tutte le mie finestre forma assomiglia così (tagliati per brevità):

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) { /*...*/ } 
} 

E io lo chiamo piace:

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

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

    return 0; 
} 

risposta

4

Vorrei rivedere leggermente il tuo progetto.

Se si è implementata l'elaborazione in una classe base, è possibile creare una sottoclasse con 2 alternative che potrebbero essere quasi intercambiabili.

Il primo potrebbe essere come il tuo, dove richiede un'operazione che restituisce un valore. (Vorrei rielaborare questo per usare Func<T> invece di avere il proprio tipo di delegato, però.

Il secondo potrebbe semplicemente eseguire una semplice azione e non fornire un valore di ritorno.Entrambi potrebbero utilizzare le stesse routine di animazione/visualizzazione/ecc. .. ma fornire un modo diverso di lavorare si potrebbe anche passare questo off ad altri metodi che utilizzano la classe base, che avrebbe fornito un sacco di flessibilità

Con questo approccio, si potrebbe chiamare questo tipo:

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

Assomiglierebbe a qualcosa:

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

No, avrete bisogno di creare un sovraccarico per farlo.

ad es.

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

Inoltre non è necessario per definire il proprio delegato, è possibile utilizzare Func<T> e azione.