How to keep or properly cast object Type?

asp.net-core c# design-patterns entity-framework-core oop

Question

Im dealing with this problem.

I have base class Worker that is abstract. Its base class for Driver and AmountBonus. That Bonus is writed based on Decorator design pattern. My decorator decorate one of property from Worker.

How it looks in code:

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
}

Im making WebApi app. I operate in data by endpoints. That is my PUT request:

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

It is obviious, that i get:

System.InvalidCastException: 'Unable to cast object of type '....Models.Bonus.AmountBonus' to type '...Models.Driver'.'

But my question is, is it any posibilities to vast that Driver object type? I needed it to edit exact same row in my database. My dbo.Workers column have column Discriminator made by Entity Framework Core and i need to have values like Driver, Farmer etc that i made and didnt mentioned in this example.

I Could make an Entity for my AmountBonus that i said, i need to have origin object type in my database. And i need to use Decorator there. Any ideas, how i can do it? Is it possible, to keep origin Type?

1
-1
1/10/2019 6:37:48 PM

Accepted Answer

You are passing actual valid worker instance to the decorator.
Make any change, decorator do, to that provided instance.
Then you will be able to save modified instance to the 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 class does not even need to inherit from Worker. Your casting problem goes away itself then
Then it look more like Visitor pattern for me ;)

1
1/12/2019 9:30:32 PM

Popular Answer

What you're doing makes no sense. Decorators are utility classes; they overlay programmatic functionality on to the classes they decorate. They are not something that can nor should be persisted to something like a database.

In other words, if your object is a Driver, then you need to keep it a Driver, not wrap it in an AmountBonus decorator and then attempt to persist that. Later, if you need whatever functionality the AmountBonus decorator adds again, you simply wrap your Driver instance in it again.

It doesn't even look like you're doing anything interesting with the decorator here, but if there is something that occurs just by the act of wrapping a Driver instance, then you'll need to fetch out somehow that wrapped Driver instance afterwards to actually save that and not your decorator.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow