多个接口实现的混乱

发布于 2024-12-04 09:57:24 字数 1244 浏览 1 评论 0原文

我有以下一组接口和类。

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 code> 并通过 IDeviceDataObject 一次。谁能帮我解决这个问题吗?

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

I have the following set of Interfaces and Classes.

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
   }
}

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; }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

星星的軌跡 2024-12-11 09:57:24

我可能在这里理解错误(并且我不知道您的整个类架构),但是为什么您的 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
}

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
}
<逆流佳人身旁 2024-12-11 09:57:24

您可以简单地转换为 IValidatableObject。

public class DeviceService 
{ 
   public bool ValidateDevice(IDeviceDataObject device) 
   { 
       IValidatableObject v = device as IValidatableObject;

       if (v != null)
           return device.Validate();
       return false;
   } 
} 

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;
   } 
} 
第七度阳光i 2024-12-11 09:57:24

您可以使您的 ValidateDevice 方法变得通用,让调用者自行传递实现正确接口组合的对象实例 - 这将允许您的接口保持独立并仍然强制类型安全:

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

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(); 
   }
}
等待我真够勒 2024-12-11 09:57:24

我从名称中推断了很多,但在我看来,IDeviceDataObjectIValidatableObject 是不同的想法。您可以拥有实现 IDeviceDataObjectIValidatableObject 或两者的对象,这似乎是合理的(是吗?)。如果这是真的,那么两个接口之间不存在“是”关系(您不会假设 IDeviceDataObjectIValidatableObject),因此从其他好像错了。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文