C# 与多接口实现的混淆
我有以下一组接口和类C# 与多接口实现的混淆,c#,oop,inheritance,interface,refactoring,C#,Oop,Inheritance,Interface,Refactoring,我有以下一组接口和类 public interface IValidatableObject { List<string> ValidationErrors { get; } bool Validate(); } public class ValidatableObject : IValidatableObject { public List<string>ValidationErrors { get; } public bool Validat
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
方法设置为泛型,让调用方传入实现正确接口组合的对象实例-这将允许您的接口保持独立,并仍然强制执行类型安全:
public class DeviceService
{
public bool ValidateDevice<T>(T device) where T: IDeviceDataObject, IValidatableObject
{
return device.Validate();
}
}
公共类设备服务
{
公共bool验证设备(T设备),其中T:IDeviceDataObject,IValidatableObject
{
返回设备.Validate();
}
}
我可能理解这里有些错误(我不知道您的类体系结构作为一个整体),但是为什么您的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
}
您可以简单地强制转换为表对象
public class DeviceService
{
public bool ValidateDevice(IDeviceDataObject device)
{
IValidatableObject v = device as IValidatableObject;
if (v != null)
return device.Validate();
return false;
}
}
我从这些名称中推断了很多,但在我看来,
IDeviceDataObject
和IValidatableObject
是两个独立的概念。您可以拥有实现IDeviceDataObject
,IValidatableObject
,或者两者都实现的对象(是吗?)。如果这是真的,那么两个接口之间就没有“是”关系(您不会假设IDeviceDataObject
是IValidatableObject
),因此从另一个接口继承一个接口似乎是错误的
对于
ValidateDevice
方法(或任何方法)--如果要将参数用作IDeviceDataObject
,则参数应为该类型。如果要将参数用作IValidatableObject
,则该参数应为该类型。如果它可能同时使用这两种功能,那么您可能希望传入一种不太特定的类型,然后进行运行时检查(使用C#“is”或“as”)以查看对象是否支持特定的接口。为什么您的ValidateDevice签名不像public bool ValidateDevice(IValidatableObject someobj)
?这不是验证方法功能的表现吗:它需要一些可验证的东西。其他一切都可以保持原样,这很公平。但是如果它是一个CreateDevice方法,需要知道它是一个传入的IDeviceDataObject,但它仍然需要具有IValidatableObject功能,那该怎么办呢?那么——因为我不知道这里的大图——所有IDeviceDataObject都应该是可验证的吗?如果是,则让IDeviceDataObject
从IValidatableObject
继承。如果不是,那么这不是解决方案。有时候真的很简单:这只是一个什么在语义上有意义的问题。依次将其转换为代码是一个相当简单的步骤。但是所有处于有效状态但未实现IValidatableObject
的设备都将无法通过验证。@Eranga-和?它们通知有效的唯一方法是实现IValidatableObject。我看不出有什么问题。API在撒谎。我希望ValidateDevice
方法基于IDeviceDataObject
契约进行验证。我必须完成ValidateDevice
的实现,我知道我还必须实现IValidatableObject
。@Eranga-不,API没有撒谎。如果对象未实现IValidatableObject,则无法验证该对象。就这么简单。为了解决您的问题,有一种叫做“文档”的东西。
public class DeviceService
{
public bool ValidateDevice(IDeviceDataObject device)
{
IValidatableObject v = device as IValidatableObject;
if (v != null)
return device.Validate();
return false;
}
}