gpt4 book ai didi

c# - C# 中的动态转换

转载 作者:太空宇宙 更新时间:2023-11-03 22:26:46 24 4
gpt4 key购买 nike

想象一下下面的情况。我有一个 XML 文档如下,

<Form>
<Control Type="Text" Name="FirstName" />
<Control Type="DateTime" Name="DateOfBirth" />
<Control Type="Text" Name="PlaceOfBirth" />
</Form>

我有一个名为 Control 的抽象类,它有一个名为 Process 的抽象方法,该方法采用 HttpRequest 的单个参数。我还有另外两个派生自 Control 的类,称为 TextControl 和 DateTimeControl。 Text 和 DateTime 都覆盖了 Process 方法以提供它们自己的实现。

我还有一个 Form 类,它有一个采用 HttpRequest 类型的单个参数的 Process 方法,以及一个采用 XmlDocument 类型的单个参数的构造函数。

创建了一个新的 Form 实例,并通过 XmlDocument 参数传入了上面的 Xml(我们如何从字符串获取 XmlDocument 是无关紧要的)。然后,我在刚刚创建的 Form 实例上调用 Process 方法,并按预期传入 HttpRequest 类型的参数。

到目前为止一切都很好。现在进入问题。

为了使控件的处理可扩展,我希望能够将类映射到控件类型。

例如。

Form.RegisterControl("Text", Text)
Form.RegisterControl("DateTime", DateTimeControl)

在 Form 的 Process 方法中,我想遍历文档中的每个 Control 节点(如何执行此操作又是无关紧要的),并根据我们的 RegisterControl 方法注册的类实例化与其类型匹配的类实例.在此阶段我可以指定它们是从 Control 派生的,但不能明确指定它们的类型。因为它们都是从 Control 派生的,所以我想调用我知道将要实现的 Process 方法。

这可能吗?如果是这样,我将如何处理?

最佳答案

(这个答案在某些方面是两个不同的答案,具体取决于您问题的含义。希望其中一个部分有帮助,无论如何:)


可能最好的方法是传入一个参数,该参数是一个函数,可用于在正确的时间创建新控件。如果您使用的是 C# 3,这很简单:

Form.RegisterControl("Text", () => new Text())

或者,您可以使它成为具有两个约束的通用方法:一个是作为控件,另一个是具有无参数构造函数。

public void RegisterControl<T>(string name) where T : Control, new()

然后调用它:

Form.RegisterControl<Text>("Text");
Form.RegisterControl<DateTimeControl>("DateTime");

RegisterControl 必须记住它正在使用的任何存储中的 typeof(T),但至少可以合理地确定 Activator.CreateInstance(Type ) 将在稍后工作 - 并且您将进行编译时检查。

不过,就我个人而言,我喜欢第一种形式的灵 active - 如果您要传递一个委托(delegate),它可以选择使用单例,或者可能是一些内部构造函数,甚至是私有(private)构造函数(取决于调用它的位置)。您也可以使用获取适当数据的委托(delegate):

Form.RegisterControl("Text", data => new Text(data));

你不能用通用约束来表达那种构造函数,而且无论如何以后调用它都会相对困难。


编辑:我和 Mehrdad 可能都误解了这个问题。您实际上是否根据控件类型对 RegisterControl 进行了不同的重载?如果是这样,那么在执行时直接调用正确重载的唯一方法是使用反射或在 C# 4 中使用动态类型。

另一种选择是使用双重分派(dispatch)——在控件本身中放置一个方法,该方法知道如何使用表单注册自己。这将在接口(interface)或基类中指定,但在具体子类中被覆盖。所以你的代码目前是:

Form.RegisterControl("Text", control);

会变成:

control.RegisterWith(Form, "Text");

然后可以毫无问题地调用正确的重载。

基本上您需要记住,重载决议是在编译时执行的,但覆盖决议是在执行时执行的 - 因此如果您想使某些东西动态化,请尝试使用多态性来处理它。

关于c# - C# 中的动态转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1114834/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com