Использование атрибутов для выполнения требований интерфейса - PullRequest
4 голосов
/ 08 июня 2010

Хорошо, я нахожусь на грани обдумывания этого.Есть ли способ объединить интерфейсы и атрибуты так, чтобы приписываемое свойство в реализующем классе выполняло контракт интерфейса?

В моем приложении я хотел бы показать список действий, который представляет собой агрегацию событий всистема, такая как новое сообщение, новая задача, которая создается / назначается / обновляется и т. д. Это всего лишь быстрый список того, что происходит.

Я думал об использовании интерфейса IIsActivity для пометки сущностей, которые нуждаютсябыть частью этой агрегации.Мне действительно нужно только показать название действия, дату, когда оно произошло, и ссылку на соответствующую область в приложении.Я не хочу применять дополнительные свойства в наследующих классах, которые просто дублируют информацию.Например, Задача имеет AssignedOn (DateTime), а Сообщение имеет CreatedOn (DateTime).И то, и другое соответствует требованию даты, чтобы считаться Деятельностью.То, что я не хочу, это отдельное свойство только для даты активности.То же самое можно сказать и о заголовке (Сообщение имеет свойство Заголовок, Задача имеет свойство Имя).

Итак, я хочу сказать: «Дайте мне что-нибудь, это IIsActivity. Внутри каждого изэти разработчики, я ожидаю, что будет свойство, помеченное атрибутом ActivityTitle, и свойство с атрибутом ActivityDate. "

Слишком много?

Ответы [ 3 ]

1 голос
/ 08 июня 2010

Я думаю, что ваш лучший подход - использовать явную реализацию интерфейса.

public interface IActivity
{
  DateTime OccurredOn { get; }
}

public class Task : IActivity
{
  public DateTime AssignedOn
  {
    get { /* implemenation */ }
  }

  DateTime IActivity.OccurredOn
  {
    get { return AssignedOn; }
  }
}

public class Message : IActivity
{
  public DateTime CreatedOn
  {
    get { /* implemenation */ }
  }

  DateTime IActivity.OccurredOn
  {
    get { return CreatedOn; }
  }
}

И тогда вы можете использовать ваши классы так:

public static void Main()
{
  Task task = new Task();
  Console.WriteLine(task.AssignedOn); // OK
  Console.WriteLine(task.OccurredOn); // Compile Error
  IActivity activity = task as IActivity;
  if (activity != null)
  {
    Console.WriteLine(activity.AssignedOn); // Compile Error
    Console.WriteLine(activity.OccurredOn); // OK
  }
}
0 голосов
/ 08 июня 2010

Хотя CLR поддерживает это, C # не поддерживает псевдонимы реализации интерфейса.Вы можете достичь этого в VB.NET, хотя:

Public Interface IActivity ' this can even be in C# ' 
  ReadOnly Property OccurredOn() As DateTime
End Interface

Public Class Task
  Implements IActivity

  Public ReadOnly Property AssignedOn() As DateTime Implements IActivity.OccurredOn
    Get
      ' implementation... '
    End Get
  End Property

End Class

Public Class Message
  Implements IActivity

  Public ReadOnly Property CreatedOn() As DateTime Implements IActivity.OccurredOn
    Get
      ' implementation... '
    End Get
  End Property

End Class

Итак, как упоминал Брайан Гидеон , явная реализация интерфейса - это то, что приближается к вашей цели в C #.

0 голосов
/ 08 июня 2010

Это не совсем ваш дизайн, но я использовал атрибуты, чтобы некоторые свойства моих классов имели желаемое значение. Я использую веб-сервис и мне нужно отправить некоторую информацию, некоторые поля требуют значения, другие - нет ...

[Serializable]
    [AttributeUsage(AttributeTargets.Property)]
    public class RequiredAttribute : Attribute
    {
        private CheckType[] _requiredtype;
        public RequiredAttribute(params CheckType[] type)
        {
            _requiredtype = type;
        }
        public CheckType[] Requires
        {
            get { return _requiredtype; }
        }
        public static bool CheckRequirements(object applyto, out string errormessages)
        { ...   }

        private static bool RequiredSucceeded(object applyto, StringBuilder resultmessage)
        { ...  }
    }
    [Serializable]
    public enum CheckType
    {
        HasValue,       // Checks that the property value is not null
        CheckMinRequirements,  // Will enforce the validation of properties on defined types
        IsNotNullorEmpty, // For strings
        HasElements,  // Elements exist on arrays
        ElementsRequirements // for collections
    }

Теперь есть пример класса, использующего атрибут

[Serializable]
    public class PurchaseInsurance
    {
        [Required(CheckType.IsNotNullorEmpty)]
        public string PartnerBookingID
        {
            get;
            set;
        }
        [Required(CheckType.IsNotNullorEmpty)]
        public string Currency
        {
            get;
            set;
        }
        public string ReferringURL;

        [Required(CheckType.HasValue, CheckType.CheckMinRequirements)]
        public PurchaserInfo Purchaser
        {
            get;
            set;
        }
        [Required(CheckType.HasValue, CheckType.ElementsRequirements)]
        public InsuranceProduct[] Products
        {
            get;
            set;
        }
...
}

Перед отправкой данных в веб-службу я проверю, соответствует ли каждое свойство их тегам атрибутов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...