Confusion with multiple interface implementation
I have the following set of Interfaces and Classes.
p开发者_运维技巧ublic 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
}
}
The problem in the service operation ValidateDevice above is that the compiler can't resolve device.Validate() because IDeviceDataObject does not implement the IValidatableObject interface.
My question is, is it then correct to change IValidatableObject
to implement IValidatableObject
. I'm a little uncertain as to whether this is good practice because the way I kind of see it, DeviceDataObject
is implementing IValidatableObject
twice - once through ValidatableObject
and once through IDeviceDataObject
. Can anyone help clear this up for me?
public interface IDeviceDataObject : IValidatableObject
{
int Id { get; set; }
string Name { get; set; }
}
I may understand something wrong here (and I dont know your class architecture as a whole), but why doesn't your ValidateDevice method just take validatable objects? The signature would look like:
public bool ValidateDevice(IValidatableObject someobj)
Isnt that what expresses the functionality of a method that does validation: it takes something that is validatable. Everything else could stay the way it is (i.e. dont let IDeviceDataObject
inherit from IValidatableObject
, as you may want to express that not every devicedataobject is also validatable for example)
A second way, if you want to make sure that ValidateDevice
only takes objects implementing IDeviceDataObject
, you could also try to cross-cast to 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
}
You could simply cast to IValidatableObject.
public class DeviceService
{
public bool ValidateDevice(IDeviceDataObject device)
{
IValidatableObject v = device as IValidatableObject;
if (v != null)
return device.Validate();
return false;
}
}
You could make your ValidateDevice
method generic to leave it up to the caller to pass in object instances that implement the right combinations of interfaces - this would allow your interfaces to remain independent and still enforce type safety:
public class DeviceService
{
public bool ValidateDevice<T>(T device) where T: IDeviceDataObject, IValidatableObject
{
return device.Validate();
}
}
I'm inferring a lot from the names, but it looks to me as if IDeviceDataObject
and IValidatableObject
are separate ideas. It seems reasonable that you could have objects which implement either IDeviceDataObject
, IValidatableObject
, or both (yes?). If this is true, then there is no "is a" relationship between the two interfaces (you wouldn't assume IDeviceDataObject
is a IValidatableObject
), so inheriting one interface from the other seems wrong.
As for your ValidateDevice
method (or any method) -- if it's going to use the argument as a IDeviceDataObject
, the argument should be of that type. If it's going to use the argument as an IValidatableObject
, the argument should be of that type. If it might use both pieces of functionality, you might want to pass in a less specific type and then do a runtime check (using C# 'is' or 'as') to see if the object supports the particular interface.
精彩评论