我正在处理此问题。
我有一个抽象的基类Worker
。其Driver
和AmountBonus
的基类。 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
,我需要具有在本示例中创建但未提及的Driver
,Farmer
等值。>
我可以为我说的AmountBonus
创建一个实体,我需要在数据库中具有原始对象类型。我需要在那里使用Decorator。任何想法,我该怎么做?是否可以保留原产地Type
?
答案 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
继承。那么您的投放问题就会自动消失
然后对我来说,它更像是访客模式;)