Sto affrontando questo problema.
Ho un Worker
classe base che è astratto. La sua classe base per Driver
e AmountBonus
. Quel Bonus
è scritto sulla base del modello di progettazione Decorator . Il mio decoratore decora una proprietà di Worker
.
Come appare nel codice:
public abstract class Worker {}
public class Driver : Worker {}
public abstract class Bonus : Worker
{
public Bonus(Worker worker) => this.worker = worker; //constructor
//decorator on worker's property
}
public class AmountBonus : Bonus
{
public AmountBonus(Worker worker) : base(worker: worker){ } //constructor
}
WebApi
facendo app WebApi
. Lavoro nei dati per endpoint. Questa è la mia richiesta PUT
:
// PUT: api/Bonus/Amount/5
[HttpPut("Amount/{id}")]
public Worker Get(int id)
{
var worker = _context.Workers.Find(id);
switch (worker)
{
case Driver d:
worker = new AmountBonus(worker) { Id = id };
//exception here
_context.Entry((Driver)worker).State = EntityState.Modified;
_context.SaveChanges();
break;
}
return worker;
}
È ovvio che ottengo:
System.InvalidCastException: 'Impossibile lanciare l'oggetto di tipo' .... Models.Bonus.AmountBonus 'per digitare' ... Models.Driver '.'
Ma la mia domanda è, c'è qualche possibilità di vasto che tipo di oggetto Driver
? Ne avevo bisogno per modificare esattamente la stessa riga nel mio database. La mia colonna dbo.Workers
ha una colonna Discriminator
fatta da Entity Framework Core e ho bisogno di avere valori come Driver
, Farmer
ecc. Che ho creato e non menzionato in questo esempio.
Potrei creare un'entità per il mio AmountBonus
che ho detto, ho bisogno di avere il tipo di oggetto di origine nel mio database. E ho bisogno di usare Decorator lì. Qualche idea, come posso farlo? È possibile mantenere il Type
origine?
Stai passando l'effettiva istanza di lavoratore valida al decoratore.
Apporta qualsiasi modifica, decoratore, a quell'istanza fornita.
Quindi sarai in grado di salvare l'istanza modificata nel database.
[HttpPut("Amount/{id}")]
public Worker Get(int id)
{
var worker = _context.Workers.Find(id);
switch (worker)
{
case Driver d:
var amountBonus = new AmountBonus(worker) { Id = id };
amountBonus.ExecuteDecoration();
_context.Entry(worker).State = EntityState.Modified;
_context.SaveChanges();
break;
}
return Ok(worker);
}
AmountBonus
classe AmountBonus
non ha nemmeno bisogno di ereditare da Worker
. Il tuo problema di casting si risolve da solo
Quindi assomiglia più a Visitor pattern per me;)
Quello che stai facendo non ha senso. I decoratori sono classi di utilità; sovrappongono la funzionalità programmatica alle classi che decorano. Non sono qualcosa che può né dovrebbe essere persistito in qualcosa come un database.
In altre parole, se l'oggetto è un Driver
, allora avete bisogno di mantenere il Driver
, non avvolgerlo in un AmountBonus
decoratore e quindi tentare di persistere questo. In seguito, se hai bisogno di qualsiasi funzionalità che il decoratore AmountBonus
aggiunge di nuovo, devi semplicemente avvolgere di nuovo l'istanza del tuo Driver
.
Non sembra nemmeno che tu stia facendo qualcosa di interessante con il decoratore qui, ma se c'è qualcosa che si verifica solo con l'atto di avvolgere un'istanza di Driver
, allora dovrai recuperare in qualche modo l'istanza del Driver
spostata in seguito per effettivamente risparmiare quello e non il vostro decoratore.