Путаница с множественной реализацией интерфейса - PullRequest
3 голосов
/ 15 сентября 2011

У меня есть следующий набор интерфейсов и классов.

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

Ответы [ 4 ]

1 голос
/ 15 сентября 2011

Я могу понять, что что-то здесь не так (и я не знаю вашу архитектуру класса в целом), но почему ваш метод 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
}
1 голос
/ 15 сентября 2011

Вы можете просто привести к IValidatableObject.

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

       if (v != null)
           return device.Validate();
       return false;
   } 
} 
0 голосов
/ 15 сентября 2011

Из названий я многое делаю, но мне кажется, что IDeviceDataObject и IValidatableObject - это отдельные идеи.Кажется разумным, что у вас могут быть объекты, которые реализуют либо IDeviceDataObject, IValidatableObject, либо оба (да?).Если это так, то между двумя интерфейсами нет отношения «есть» (вы не предполагаете, что IDeviceDataObject - это IValidatableObject), поэтому наследование одного интерфейса от другого кажется неправильным.Что касается вашего ValidateDevice метода (или любого метода) - если он собирается использовать аргумент в качестве IDeviceDataObject, аргумент должен быть такого типа.Если он будет использовать аргумент в качестве IValidatableObject, аргумент должен иметь тип , который .Если он может использовать обе части функциональности, вы можете передать менее конкретный тип, а затем выполнить проверку во время выполнения (используя C # «is» или «as»), чтобы определить, поддерживает ли объект определенный интерфейс.

0 голосов
/ 15 сентября 2011

Вы можете сделать свой метод ValidateDevice универсальным, чтобы предоставить вызывающей стороне возможность передавать экземпляры объектов, которые реализуют правильные комбинации интерфейсов - это позволит вашим интерфейсам оставаться независимыми и при этом обеспечивать безопасность типов:

public class DeviceService
{
   public bool ValidateDevice<T>(T device) where T: IDeviceDataObject, IValidatableObject
   {
       return device.Validate(); 
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...