【问题标题】:Dynamic dispatch to derived class in C#在 C# 中动态分派到派生类
【发布时间】:2012-05-21 10:04:44
【问题描述】:

我正在尝试执行以下操作:

public abstract BaseClass {

  public virtual void ReceiveEvent(Event evt)
    {
        ProcessEvent(evt as dynamic);
    }

    private void ProcessEvent(object evt)
    { 
        LogManager.Log(@"Received an event that is not being processed! 
                        Dispatch fallback");
    }
}

public DerivedClass: BaseClass {

    private void ProcessEvent(SpecificEvent evt)
    { 
        LogManager.Log("Processing Event");
    }
}

SpecificEvents 命中后备方法,而不是派生类中的方法。我一直在同一个类中使用动态调度,发现它非常有用/干净。如上例所示,它是否不适用于派生类?

编辑: 答案似乎有些混乱。基本上我一直使用以下设计:

public class SomeClass{

    public void DoSomethingDispatcher(SomeObject obj)
    {
        ProcessObject(obj as dynamic);
    }

    private void DoSomething(SomeObjectType1 obj)
    { 

    }

    private void DoSomething(SomeObjectType2 obj)
    { 

    }

    private void DoSomething(SomeObjectType3 obj)
    { 

    }

    private void DoSomething(object obj) //fallback
    { 

    }
}

非常适合您事先不知道确切的类型并且不想使用大的 switch 语句。只是想知道这是否可以通过继承来实现,其中基类包含回退方法,派生类包含所有更具体的方法。

【问题讨论】:

  • 我的猜测是在 BaseClass 而不是 DerivedClass 上调用了 ReceiveEvent。您是否尝试过覆盖 DerivedClass 上的 ReceiveEvent?它是虚拟的,所以你可以做public override void ReceiveEvent(Event evt) 这里有一些关于虚拟方法的更多信息:msdn.microsoft.com/en-us/library/aa645767%28v=vs.71%29.aspx

标签: c# c#-4.0 dispatch


【解决方案1】:

它对你不起作用,因为即使 evt 是动态传递的,ProcessEvent 也不会被声明为虚拟的。这意味着当对 ProcessEvent 的调用被编译时,它被链接到基类中找到的方法的唯一实现,而派生类中的方法永远不会被执行。此外,您不能简单地将 ProcessEvent 声明为虚拟,因为派生类中的签名会有所不同。

为了让您的代码按预期工作,您可以在派生类中覆盖 ReceiveEvent,使其保持完全相同:

  public override void ReceiveEvent(Event evt)
    {
        ProcessEvent(evt as dynamic);
    }

如果要管理基类中未处理的事件,只需将基类中Process事件的修饰符更改为protected(否则被重写版本的ReceiveEvents调用时无法执行)。

【讨论】:

  • 是的,我现在就是这样写的。猜猜这是最接近的解决方案。我希望我可以将后备移动到基类,但根据您描述编译过程的方式,这似乎是不可能的。干杯。
  • 哦,我刚刚注意到最后一段。我会试试看!
【解决方案2】:

如果方法在基类中不是virtual/abstract,并且方法在派生类中没有标记为override,则永远不会起作用。

另外,我不明白这里dynamic的用法。

【讨论】:

  • 这里的动态被用作将未知对象类型路由到相应处理程序的好方法,而不使用 switch 语句
【解决方案3】:

当你的“evt”点击 ProcessEvent 时,它的类型是什么?

你可以看看Using Type dynamic

类型是静态类型,但是动态类型的对象绕过 静态类型检查。在大多数情况下,它的功能就像它有类型 对象。

所以,evt 不是SpecificEvent

【讨论】:

  • 首先,动态将被视为对象。然后,您的继承似乎不正确,没有“虚拟”/“抽象”/“覆盖”甚至“新”方法。您可以尝试在 BaseClass 中的 ProcessEvent 方法上放置 virtual 并覆盖 DerivedClass。
【解决方案4】:

要获得预期的行为,您应该重写虚拟方法:

public DerivedClass: BaseClass
{
  private override void ReceiveEvent(Event evt)
  { 
      // Process your event here.
  }
}

使用此代码,不会调用基类中的ReceiveEvent,因此不会调用备用ProcessEvent

没有理由使用dynamic

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多