与多个接口实现混淆

本文关键字:实现 接口 | 更新日期: 2023-09-27 18:08:32

我有以下一组接口和类。

public interface IValidatableObject
{
   List<string> ValidationErrors { get; }
   bool Validate();
}
public class ValidatableObject : IValidatableObject
{
   public List<string>ValidationErrors { get; }
   public bool Validate()
   {
      //dostuff
   }
}
public interface IDeviceDataObject
{
   int Id { get; set; }
   string Name { get; set; }
}
public class DeviceDataObject : ValidatableObject, IDeviceDataObject
{
   public int Id { get; set; }
   public string Name { get; set; }
}
public class DeviceService
{
   public bool ValidateDevice(IDeviceDataObject device)
   {
       return device.Validate(); // This throws a compiler error
   }
}

上面的服务操作ValidateDevice中的问题是编译器无法解析device.Validate(),因为IDeviceDataObject没有实现IValidatableObject接口。

我的问题是,改变IValidatableObject来实现IValidatableObject是正确的吗?我有点不确定这是否是一个好的实践,因为我看到它的方式,DeviceDataObject实现了IValidatableObject两次-一次通过ValidatableObject,一次通过IDeviceDataObject。有人能帮我澄清一下吗?

public interface IDeviceDataObject : IValidatableObject
{
   int Id { get; set; }
   string Name { get; set; }
}

与多个接口实现混淆

我可能在这里理解了一些错误(我不知道你的类架构作为一个整体),但为什么你的ValidateDevice方法不只是接受可验证的对象?签名看起来像:

public bool ValidateDevice(IValidatableObject someobj)

这不就是表达验证方法的功能吗?它接受可验证的东西。其他一切都可以保持原样(例如,不要让IDeviceDataObject继承IValidatableObject,因为您可能想表达并非每个devicedataobject也可验证)

第二种方法,如果你想确保ValidateDevice只接受实现IDeviceDataObject的对象,你也可以尝试交叉强制转换到IValidatableObject:
public bool ValidateDevice(IDeviceDataObject someobj)
{
    if(someobj is IValidatableObject)
    {
        return ((IValidatableObject)device).Validate();
    }
    return //something that makes sense if the device is not validatable
}

可以直接转换为IValidatableObject

public class DeviceService 
{ 
   public bool ValidateDevice(IDeviceDataObject device) 
   { 
       IValidatableObject v = device as IValidatableObject;
       if (v != null)
           return device.Validate();
       return false;
   } 
} 

你可以让你的ValidateDevice方法泛型,把它留给调用者来传递实现接口正确组合的对象实例——这将允许你的接口保持独立,并且仍然强制类型安全:

public class DeviceService
{
   public bool ValidateDevice<T>(T device) where T: IDeviceDataObject, IValidatableObject
   {
       return device.Validate(); 
   }
}

我从名字中推断了很多,但在我看来,IDeviceDataObjectIValidatableObject是分开的想法。这似乎是合理的,你可以有对象实现IDeviceDataObject, IValidatableObject,或两者(是吗?)。如果这是真的,那么两个接口之间没有"是"关系(您不会假设IDeviceDataObjectIValidatableObject),因此从一个接口继承另一个接口似乎是错误的。

对于您的ValidateDevice方法(或任何方法)—如果它将参数用作IDeviceDataObject,则参数应该是该类型。如果要将参数用作IValidatableObject,则参数应该是类型的。如果它可能使用这两种功能,你可能想传入一个不太具体的类型,然后做一个运行时检查(使用c# 'is'或'as'),看看对象是否支持特定的接口。