DI Intercettazione e UI

1

Contribuisco a un progetto open source che utilizza pesantemente il modello di progettazione iniezione-ctor. Recentemente, c'è stata una discussione sull'uso dell'intercettazione per alcune cose, tra cui l'iniezione di comandi dell'interfaccia utente a un modello di visualizzazione e il binding corretto del comando al valore corretto.

Ad esempio, abbiamo un comando:

public class FooCommand : CommandBase    // CommandBase implements ICommand
{
    public bool CanExecute(object obj);
    public void Execute(object obj);
}

Ne abbiamo molti e li iniettiamo nel modello di visualizzazione con Ninject. Potrebbe essere rilevante il fatto che in questo caso specifico i comandi siano contrassegnati con un attributo, quindi sappiamo quale sottoinsieme deve essere iniettato:

public class FooViewModel : ViewModelBase
{
    public FooViewModel(IEnumerable<CommandBase> commands) {}
}

Ora, nella classe definita sopra, procediamo in questo modo:

public class FooViewModel : ViewModelBase
{
    public FooCommand FooCommand { get; }

    public FooViewModel(IEnumerable<CommandBase> commands)
    {
        FooCommand = commands.SingleOrDefault(command => command is FooCommand);
    }
}

L'istanza pubblica di FooCommand è associata agli elementi dell'interfaccia per determinate azioni.

Ora, quando abbiamo provato a lavorare con questo usando i comandi intercettati, tutto si è rotto. Quando abbiamo intercettato la nostra implementazione e abbiamo iniettato l'implementazione di Ninject, abbiamo ricevuto solo un mucchio di implementazioni CommandBase , quindi non sappiamo quale comando legare a quale valore. In sostanza, ci affidiamo a un'implementazione specifica oa qualsiasi implementazione derivata per associare a un comando specifico; Ninject, tuttavia, restituisce valori a un livello di astrazione più alto del necessario.

Ci sono due metodi che posso vedere per risolvere questo problema - A) in qualche modo rendere Ninject intercetta la classe specifica invece della sua interfaccia, e B) aggiunge un campo astratto a CommandBase da usare per capire cosa è cosa. Non sono sicuro di come fare A, o anche se può essere fatto - almeno, non ho avuto successo con esso. B, d'altra parte, sembra essere 1) aggiungere informazioni ridondanti (il tipo già fornisce questo valore - quando non usiamo l'intercettazione, cioè), e 2) aggiungendo un altro possibile posto per farlo rompere. Quali sono i tuoi consigli per questo?

    
posta Hosch250 13.08.2016 - 17:19
fonte

1 risposta

4

Questo è un modo abbastanza maciullato per fare DI. In pratica stai facendo localizzatore di servizi senza il localizzatore di servizio ... E il motivo per cui non funziona è esattamente questo: stai usando uno strumento per cercare di fare qualcosa che non era destinato a fare.

La soluzione è semplice: devi solo iniettare le classi reali di cui hai bisogno richiedendole così come sono.

Quello che stai facendo qui è un modello valido per alcuni casi (iniettare un numero sconosciuto di classi che estendono la stessa interfaccia e che tutti hanno bisogno di eseguire un lavoro), ma non il tuo.

    
risposta data 13.08.2016 - 20:43
fonte

Leggi altre domande sui tag