如何在仅在base中实现的继承类中调用InvmberMember

时间:2009-06-18 13:03:01

标签: c# inheritance

方案是我正在更改“请求”的状态,有时新状态是暂时的,需要立即更改为其他状态。所以我在我的基类中的一个方法,WorkflowCommandBase:

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

最后一行尝试再次为新状态执行该方法(来自继承的类,名为Type),但我调用的方法在calledType中不存在,它在底层实现。有可能这样做吗?或者,如果存在这种情况,是否需要覆盖继承类中的Execute方法?

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

这是类图的一部分,如果有帮助的话。

Class Diagram

2 个答案:

答案 0 :(得分:2)

那么,根据您的评论,您可能会在问题中写下的内容与您尝试执行的操作之间存在不连续性。所以我会尝试覆盖所有的基础。

如果Execute方法是静态的并且在基类上定义,则需要将BindingFlags.FlattenHierarchy添加到绑定标志:

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

这似乎是最可能的问题,因为你说它没有找到方法,但是这个标志只在你搜索静态成员时才有效。

另一方面,如果方法不是静态,那么你拥有的绑定标志是正确的,但你需要一个类型的实例来运行它。根据构造混凝土类型的复杂程度,您可以使用Activator类来逃避,否则您可能需要创建某种类型的工厂。

答案 1 :(得分:2)

@Martin:谢谢你的帮助。

我发布这封信以防万一。

    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
    }