如何保持或正确投射对象类型?

时间:2019-01-10 18:37:48

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

我正在处理此问题。

我有一个抽象的基类Worker。其DriverAmountBonus的基类。 Bonus是基于Decorator design pattern写的。我的装饰器装饰了Worker中的一个属性。

它在代码中的外观:

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应用。我按端点处理数据。这是我的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;
    }

我明白:

  

System.InvalidCastException:'无法转换类型为'.... Models.Bonus.AmountBonus'的对象来类型为'... Models.Driver'。'

但是我的问题是,Driver对象类型是否可能具有广阔的前景?我需要它来编辑数据库中的同一行。我的dbo.Workers列具有由Entity Framework Core制作的列Discriminator,我需要具有在本示例中创建但未提及的DriverFarmer等值。

我可以为我说的AmountBonus创建一个实体,我需要在数据库中具有原始对象类型。我需要在那里使用Decorator。任何想法,我该怎么做?是否可以保留原产地Type

2 个答案:

答案 0 :(得分:1)

您在做什么毫无意义。装饰器是实用程序类。它们将编程功能叠加到它们装饰的类上。它们不是也不能持久化到数据库之类的东西。

换句话说,如果您的对象是Driver,则需要将其保留为Driver,而不是将其包装在AmountBonus装饰器中,然后尝试保留。以后,如果您需要再次使用AmountBonus装饰器提供的功能,则只需将Driver实例再次包装在其中。

看起来您在这里用装饰器没有做任何有趣的事情,但是如果仅通过包装Driver实例而发生了某些事情,那么您需要提取之后以某种方式包装了Driver实例,以实际保存那个而不是您的装饰器。

答案 1 :(得分:1)

您正在将实际的有效工作程序实例传递给装饰器。
装饰器对提供的实例进行任何更改。
然后,您将能够将修改后的实例保存到数据库中。

[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类甚至不需要从Worker继承。那么您的投放问题就会自动消失
然后对我来说,它更像是访客模式;)