C# 带装饰图案的类型铸造

C# 带装饰图案的类型铸造,c#,casting,decorator,C#,Casting,Decorator,我有一个电机接口和各种特定于供应商的接口实现 public interface IMotor { void Home(); void Move(); } public class VenodorAMotor : IMotor { public void Home() { /*home motor*/ } public void Move() { /*move motor*/ } } 我正在装饰IMotor,为它的home方法添加一些功能 public

我有一个电机接口和各种特定于供应商的接口实现

public interface IMotor
{
  void Home();
  void Move();
}

public class VenodorAMotor : IMotor
{
  public void Home()
  { /*home motor*/  }

  public void Move()
  { /*move motor*/  }     
}
我正在装饰IMotor,为它的home方法添加一些功能

public class HomeAdjustmentDecorator : IMotor
{
  private IMotor decoratedMtr;

  public static explicit operator VendorAMotor(HomeAdjustmentDecorator mtr) 
  { return (VendorAMotor)mtr.decoratedMtr; }

  public HomeAdjustmentDecorator(IMotor mtr)
  { 
    if(! mtr is VenodorAMotor)
      throw new Exception("HomeAdjustmentDecorator can only decorate VenodorAMotor objects");
    decoratedMtr = mtr; 
  }

  public void Home()
  {
    decoratedMtr.Home();
    double adjustment = ((VendorAMotor)myMotor).GetHomeAdjustment();//vendor-specific functionality
    Log(adjustment);
  }

  public void Move()
  { decoratedMtr.Move();  }  
}
我无法控制
VendorAMotor
的创建,因此我无法轻松使用继承

问题在于现有代码已经将未修饰的IMotor强制转换到其实现类,以访问其他特定于供应商的功能。由于HomeAdjustmentDecorator未继承VenodorAMotor,因此强制转换失败

IMotor myDecoratedMotor;//Implementation is HomeAdjustmentDecorator composed of VendorAMotor
...
((VendorAMotor)myDecoratedMotor).DoOtherVendorSpecificStuff();
我已尝试覆盖如图所示的强制转换操作符,但这不起作用。我得到一个InvalidCastExection选项:“无法将'HomeAdjustmentDecorator'类型的对象强制转换为'VenodorAMotor'类型。”
一切都很好。如果未执行显式强制转换运算符重写,则不会命中断点。问题是,是否未执行此强制转换覆盖?

我在这里发现了一个类似的问题: 但这并没有什么帮助

我认为答案如下:
但我认为我遗漏了一些微妙的细节。

我认为从接口转换到具体类来调用特定方法是一种不好的做法,正如您所看到的,它已经造成了问题

转换运算符不适用于接口,因为在编译时,没有具体的类型(由编译器使用)来查找此类运算符

鉴于您无法访问
IMotor
的源代码,您可能希望至少集中cast并使用以下命令扩展
IMotor

并更改为:

IMotor motor = new VendorAMotor();
IMotor decorated = new HomeAdjustmentDecorator(motor);

// Both should work
motor.DoOtherVendorSpecificStuff();
decorated.DoOtherVendorSpecificStuff();

我认为从一个接口转换到一个具体的类来调用一个特定的方法是一种不好的做法,正如您所看到的,它已经造成了问题

转换运算符不适用于接口,因为在编译时,没有具体的类型(由编译器使用)来查找此类运算符

鉴于您无法访问
IMotor
的源代码,您可能希望至少集中cast并使用以下命令扩展
IMotor

并更改为:

IMotor motor = new VendorAMotor();
IMotor decorated = new HomeAdjustmentDecorator(motor);

// Both should work
motor.DoOtherVendorSpecificStuff();
decorated.DoOtherVendorSpecificStuff();

正如其他人提到的,将接口与类型转换混合到具体实现中是一种糟糕的做法。 注意:通常可以检查对象是否实现了一个或多个其他接口:

if (motor is IDisposable disposable)
    disposable.Dispose();
原因:接口的存在是为了定义对象的行为。接口用于确保任何实现都适用于您的功能。当你检查具体的执行情况时,你就放弃了Liskov替代原则

对于您的原始问题,您可以定义其他接口:

public interface IMotorWithVendorStuff: IMotor
{
    DoOtherVendorSpecificStuff();
}
public class VendorAMotorAdapter: IMotorWithVendorStuff
{
    // ...
}
以及用于
VendorAMotor
的适配器,以实现该接口:

public interface IMotorWithVendorStuff: IMotor
{
    DoOtherVendorSpecificStuff();
}
public class VendorAMotorAdapter: IMotorWithVendorStuff
{
    // ...
}

在将
IMotor
转换为
VendorAMotor
的所有地方,都应该使用
IMotorWithVendorStuff
,正如其他人提到的,将接口与类型转换混合到具体实现中是一种不好的做法。 注意:通常可以检查对象是否实现了一个或多个其他接口:

if (motor is IDisposable disposable)
    disposable.Dispose();
原因:接口的存在是为了定义对象的行为。接口用于确保任何实现都适用于您的功能。当你检查具体的执行情况时,你就放弃了Liskov替代原则

对于您的原始问题,您可以定义其他接口:

public interface IMotorWithVendorStuff: IMotor
{
    DoOtherVendorSpecificStuff();
}
public class VendorAMotorAdapter: IMotorWithVendorStuff
{
    // ...
}
以及用于
VendorAMotor
的适配器,以实现该接口:

public interface IMotorWithVendorStuff: IMotor
{
    DoOtherVendorSpecificStuff();
}
public class VendorAMotorAdapter: IMotorWithVendorStuff
{
    // ...
}

您应该在将
IMotor
转换为
VendorAMotor
的所有位置使用
IMotorWithVendorStuff
,因为装饰器功能特定于
VendorAMotor
实现,您可以只向
VenodorAMotor
类添加必要的代码吗?假设
myDecoratedMotor
IMotor
,并且您无法控制
IMotor
则无法向其添加转换(只能向自己的类添加转换)。。。因此,你可能想澄清你到底想要实现什么,以及你愿意做些什么来达到目标…@AlexeiLevenkov;你能为我澄清一下你的说法吗:“你没有办法给它添加转换(你只能给自己的类添加转换)”?我试图将一个
IMotor
,实现是
HomeAdjustmentDecorator
,转换为
VenodorAMotor
HomeAdjustmentDecorator
由它组成(作为
IMotor
)。我控制着“HomeAdjustmentDecorator”,并且知道它是由我试图将它投射到的东西组成的。谢谢@用户3532473我没有收到你的评论。基于这个问题,它听起来像是
IMotor-mydecordementedmotor-根据您的约束,您没有机会使铸件正常工作。。。的确
家庭调整装饰器myDecoratedMotor。。。;((VenodorAMotor)MydecordedMotor).其他供应商指定的UFF()将与您的代码完美配合。。。但比你想问的还要多?@AlexeiLevenkov。((VenodorAMotor)MydecordedMotor).其他供应商指定的UFF();不起作用。我想这正是我想问的——为什么它不起作用或者我错过了什么?似乎另一个悬而未决的答案可能是这样的:“转换运算符不适用于接口,因为在编译时,(编译器)没有具体类型可用于查找此类运算符。”因为decorator功能特定于
VenodorAMotor
实现,您可以只向
VenodorAMotor
类添加必要的代码吗?假设
myDecoratedMotor
IMotor
,并且您无法控制
IMotor
则无法向其添加转换(只能向自己的类添加转换)。。。因此,你可能想澄清你到底想要实现什么,以及你愿意做些什么来达到目标…@AlexeiLevenkov;你能为我澄清一下你的说法吗:“你没有办法给它添加转换(你只能添加conv