2016-05-30 6 views
9

Ho una classe # c che fornisce operazioni virtuali. Per ogni operazione esiste una versione sincrona e asincrona.Mostra un avvertimento quando viene esclusa solo una coppia di metodi o proprietà

public class Foo{ 
    public virtual void Bar(){..}; 
    public virtual Task BarAsync(){..}; 

    ... 
} 

desidero avere il compilatore mostra un avviso se viene sostituita una sola versione dell'operazione (sincrono o la versione asincrona dell'operazione) come il compilatore avverte quando si ignora Equals senza sovrascrivere GetHashCode o vice versa.

Interrogato in modo più generale: È possibile applicare l'override di un metodo o proprietà per forzare l'override di altre proprietà o metodi (tramite avvisi del compilatore).

+0

Si dovrà scrivere un [analizzatore Roslyn] (https://github.com/dotnet/roslyn-analyzers). –

+0

Come ha risposto HimBromBeere, sembra più logico quindi semplicemente creare una classe di base astratta e inserire qualsiasi codice effettivamente esistente che verrà sovrascritto nel tuo caso qui in un'implementazione esistente. – Nyerguds

+0

La classe fa parte di un piccolo framework e l'architettura proposta ne complica l'utilizzo perché consumare Foo non viene eseguito allo stesso modo di Foo. – HCL

risposta

3

Anche se questa non è una risposta alla tua domanda, ti sto chiedendo un approccio in cui non hai nemmeno bisogno dell'avvertimento.

Perché non creare uno classi astratte con i membri overridable e una tenuta senza:

public class Foo{ 
    public virtual void Bar(){..} 
    public virtual Task BarAsync(){..} 
} 

public abstract class ImplementIt : Foo { 
    public abstract override void Bar(); 
    public abstract override Task BarAsync(); 
} 
public sealed class DoNotImplementIt : Foo { 
    public override void Bar() {..} 
    public override Task BarAsync() {..} 
} 

Ora cliente può progettare se ha bisogno di un'implementazione del Foo whith vostro comportamento di default (= DoNotImplementIt) o se ha bisogno di un personalizzabile versione con ImplementIt. Nel primo caso è costretto a scavalcare i membri in quest'ultimo caso no.

Questo approccio è molto più pulito per il tuo utente API, poiché sa cosa ignorare la catena di ereditarietà invece di fare affidamento su avvisi disordinati di cui nessuno in realtà si prende cura.

Un approccio ancora migliore sarebbe quella di definire Foo come un'interfaccia che sia ImplementIt e DoNotImplementIt attuare (suona strano, ma si ottiene). Salva da questo abstract override. In questo modo puoi anche nascondere la tua interfaccia dall'esterno rendendola internal e rendere solo le classi di implementazione accessibili dall'API.

+0

Vuoi dire che la classe astratta deriva dalla prima classe?Ci sono problemi con l'accessibilità ('public'), e con la denominazione (' Bar' non può essere un metodo di una 'Bar' di classe). –

+0

@JeppeStigNielsen Yeap, sto superando la classe 'Foo'. Ho anche cambiato i nomi dei membri. – HimBromBeere

+0

Questo mi ha aiutato, ma hai ancora un problema con la classe derivata 'Bar' è' public' mentre la sua classe base non lo è. –

0

È possibile scrivere un custom Code Analyzer. Non l'ho mai usato da solo. Abbiamo iniziato a utilizzare FxCop e abbiamo scritto alcune regole personalizzate per questo. Ma è piuttosto difficile da fare. Con Roslyn, questo dovrebbe essere molto più facile.

1

Codice di scrittura che ha lo stesso effetto dell'applicazione.

  • Creare un'interfaccia contenente i metodi/proprietà da sovrascrivere.
  • Scrivere una funzione (sovrascrivibile) che restituisce l'interfaccia.
  • Quindi, quando questo viene annullato, tutte le funzioni vengono sostituite contemporaneamente.

Esempio:

public interface IBarMethods 
{ 
    void Bar(); 
    Task BarAsync(); 
} 

public class Foo 
{ 
    public virtual IBarMethods DeMethods() 
    { 
     // return class containing default methods. 
    } 
} 

public class ImplementIt : Foo 
{ 
    public override IBarMethods DeMethods() 
    { 
     // return different methods. 
    }  
} 
+1

Quando si fa 'Foo' si può anche avere un metodo (sigillato)' Barra' e un metodo (sigillato) 'BarAsync' che ottiene questo oggetto' IBarMethod' e chiama il metodo appropriato. Da notare che probabilmente andrei con una proprietà, piuttosto che con un metodo, per ottenere l'istanza di 'IBarMethods' (uno' protected' nel mio caso). – Servy

Problemi correlati