简体   繁体   中英

Changing types passed in to virtual methods

I have a question regarding changing parameter types in virtual methods. First I'll explain the scenario.

This is the base interface for users that can execute commands

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

This is an extension of that base interface, that requires users to have the concept of Eminence

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

Now this is the base abstract UserCommand class that defines commands that IUserThatExecutesCommands use

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

Here is an extension of that class that introduces the concept of Eminence, thus requires a IUserThatExecutesEminenceCommands to use. At the moment this causes a compiler error because I have changed the type of use that is passed in.

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

My question is, is there a way that I can override the CanBeExecutedBy function so that I can change the type of user that is passed in? I want to be able to extend the UserCommand class, but at the moment I am unable to due to this issue.

Thanks

Try this:

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

Once you establish a signature for a virtual function, it becomes a contract that you cannot change. However, you can test the user argument to CanBeExecutedBy and see if it supports any desired interface. So, your method would look like this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM