Изменение типов, передаваемых в виртуальные методы - PullRequest
2 голосов
/ 14 января 2012

У меня вопрос по поводу изменения типов параметров в виртуальных методах. Сначала я объясню сценарий.

Это базовый интерфейс для пользователей, которые могут выполнять команды

public interface IUserThatExecutesCommands
{
   bool IsInRole(string role);
} 

Это расширение базового интерфейса, требующее, чтобы пользователи имели концепцию Eminence

public interface IUserThatExecutesEminenceCommands : IUserThatExecutesCommands
{
   int Eminence { get; }
}

Теперь это базовый абстрактный класс UserCommand, который определяет команды, которые IUserThatExecutesCommands используют

public abstract class UserCommand
{
   public virtual bool CanBeExecutedBy(IUserThatExecutesCommands user)
   {
       // For the purpose of simplification I have not included the actual implementation of this method.
       return UserIsInOneOfAllowedRoles(user);
   }
}

Вот расширение этого класса, которое вводит понятие возвышения, поэтому требует IUserThatExecutesEminenceCommands для использования. На данный момент это вызывает ошибку компилятора, потому что я изменил тип использования, который передается.

public abstract class EminenceCommand : UserCommand
{
        public override bool CanBeExecutedBy(IUserThatExecutesEminenceCommands user)
        {
            return user.Eminence >= _requiredEminence;
        }
}

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

Спасибо

Ответы [ 2 ]

0 голосов
/ 14 января 2012

Как только вы устанавливаете подпись для виртуальной функции, она становится контрактом, который вы не можете изменить. Однако вы можете проверить аргумент user на CanBeExecutedBy и посмотреть, поддерживает ли он какой-либо нужный интерфейс. Итак, ваш метод будет выглядеть так:

public override bool CanBeExecutedBy(IUserThatExecutesCommands user)
{
    IUserThatExecutesEminenceCommands u = user as IUserThatExecutesEminenceCommands;
    if (u == null)
    {
        // TODO: Ignore the arg, throw an exception or do something else.
        return false;
    }

    return u.Eminence >= _requiredEminence;
}
0 голосов
/ 14 января 2012

Попробуйте это:

public abstract class EminenceCommand : UserCommand 
{ 
        public override bool CanBeExecutedBy(IUserThatExecutesCommands user) 
        { 
            // Dynamically check the type of user passed in and only check priveleges if correct type
            IUserThatExecutesEminenceCommands u = user as IUserThatExecutesEminenceCommands;
            if( u == null) {
                 return false;
            }
            return u.Eminence >= _requiredEminence; 
        } 
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...