简体   繁体   中英

How do I InvokeMember in inherited class that is only implemented in base

The scenario is I am changing the status of a "request" and sometimes the new status is transitory and needs to immediately change to another status. So I'm in a method in my base class, WorkflowCommandBase:

    public virtual Request Execute()
    {
        ChangeRequestStatus();
        QueueEmails();
        TrackRequestStatus();
        return ExecuteAutoTransitionStatus(GetTransitionStatus());
    }

The last line tries to execute the method again for the new status (from the inherited class, calledType), but the method I am calling doesn't exist in calledType, it is implemented here in the base. It is possible to do this? Or do I need to override the Execute method in the inherited classes when this situation exists?

private Request ExecuteAutoTransitionStatus(string commandName)
{
    if (String.IsNullOrEmpty(commandName))
    {
        return Request;
    }

    Type calledType = Type.GetType(commandName);
    return (Request)calledType.InvokeMember(
           "Execute",
           BindingFlags.InvokeMethod
                | BindingFlags.Public | BindingFlags.Instance,
           null,
           null,
           new Object[]
               {Request, TarsUser, GrantRepository, TrackingRepository});
    }

Here's part of the class diagram, if it helps.

类图 .

Well, based on your comments there may be a discontinuity from what you have written in your question and what you are trying to do. So I'll try and cover all the bases.

If the Execute method is static and defined on a base class you need to add the BindingFlags.FlattenHierarchy to your binding flags:

 BindingFlags.InvokeMethod | BindingFlags.Public
 | BindingFlags.Static | BindingFlags.FlatternHierarchy

This seems the most likely problem because you say that it isn't finding the method, but this flag is only effective if you are searching for a static member.

On the other hand if the method isn't static then the binding flags that you have are correct, but you'll need an instance of the type to run it against. Depending on how complicated it is to construct your concrete type you may be able to get away with just using the Activator class, otherwise you may need to create a factory of some kind.

@Martin: Thanks for your help.

I'm posting this in case it might help someone else.

    private Request ExecuteAutoTransition(Type newStatus)
    {
        // No transition needed
        if (newStatus == null)
        {
            return Request;
        }

        // Create an instance of the type
        object o = Activator.CreateInstance(
            newStatus, // type
            new Object[] // constructor parameters
                {
                    Request,
                    TarsUser,
                    GrantRepository,
                    TrackingRepository
                });

        // Execute status change
        return (Request) newStatus.InvokeMember(
                             "Execute", // method
                             BindingFlags.Public 
                                | BindingFlags.Instance 
                                | BindingFlags.InvokeMethod, // binding flags
                             Type.DefaultBinder, // binder
                             o, // type
                             null); // method parameters
    }

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