【问题标题】:Dynamic Objects Call relative functionality everywhere to extend a liabrary C#动态对象随处调用相关功能以扩展库 C#
【发布时间】:2018-04-27 06:07:44
【问题描述】:

我在同一个父类“Control”下有不同类型的对象。 我有一个 List,我知道它可以有 VideoControl、HtmlControl 等的引用。这些都是'控制'。调试还显示运行时转换正确地将它们解析为相关 Control 并且所有其他特定属性都存在。

现在这些 Control 对象包含在两个项目中,并且我知道使用 signalR 我将收到多个类型的 Control 对象的序列化列表。

我想在每个控件上调用 Draw 函数,但我的 Xamarin.Android 项目知道如何以自己的方式Draw wach 控件。 p>

          foreach (Control control in listControls)
            {
                try
                {

                   control.Draw(this, myLayout);

                }
                catch (Exception ex)
                {
                }
            }

附: Draw 是在一个接口中定义的,因此它被强加给每个控件。我的问题是我想让所有项目都能够自行扩展或提供功能,并用我封装的数据绘制每个控件。

我已经搜索了很多,并找到了一种可能的方法,即 扩展方法,但问题是我必须进行 显式类型转换,这将再次使我的代码冗长而困难处理。

为了进一步的帮助,如果可以在没有显式类型转换的情况下处理我的扩展方法,我将添加它们。

    public static void Render(this Control Player, object context, object container)
    {
    }

    public static void Render(this VideoPlayer Player, object context, object container)
    {

    }
    public static void Render(this HTMLControl Player, object context, object container)
    {
    }
    public static void Render(this Button Player, object context, object container)
    {
    }

如果我不进行类型转换,那么每次我的类型 Control 的扩展方法都会运行,但我想为每个对象运行相关方法。

通过一些部分实现或一些扩展方法或其他方式来处理这个问题的可能方法是什么。

【问题讨论】:

  • 如果控制方法和它的派生类是你的,你为什么还要将Draw/Render方法定义为扩展方法呢?为什么不在类中实现它,让 .NET 的 OOP 代码完成它的工作?
  • 因为我正在编写一个要包含在两个或多个项目中的类库,并且我希望它们能够在每个对象上调用 Draw 并为每个控件提供 Draw 逻辑。就像有人在 Xamarin Android 或 Windows 窗体或 WPF 中实现它一样,您只需要在每个控件上调用 Draw 并在您自己的函数中调用它。
  • 把Render方法做成Control类的抽象方法,然后在各个子类中实现。
  • Control 是你的接口,还是实现你的接口的类?如果是后者,就照 Evk 说的做。如果不是,我不明白你的问题/问题。
  • Control是一个实现IControl的类

标签: c# design-patterns dynamic extension-methods


【解决方案1】:

您应该为此使用普通的 OOP 功能。你有你的控制界面:

public interface IControl
{
    void Draw();
}

还有一个抽象基类:

public abstract class Control
{
    // Use abstract if you don't want to have a default
    // Draw() method in the base Control:
    public abstract void Draw();

    // Use abstract if you do want to have a default
    // Draw() method in the base Control:
    public virtual void Draw()
    {
        // basic drawing code here
    }
}

然后你就有了你的派生类:

public class Button : Control
{
    public override void Draw()
    {
        // custom drawing code here
    }
}

然后终于使用它:

List<IControl> controls = new List<IControl>();
controls.Add(new Button());
controls.Add(new Player());
controls.Add(new Image());

foreach (IControl control in controls)
{
    control.Draw();
}

【讨论】:

  • 我需要通过包含库在单独的项目中提供 Draw 功能,我可以重新定义或部分提供 Draw 的实现。这个解决方案很好,并且可以在同一个程序集中继续工作。
  • 为什么您认为它在另一个程序集中不起作用?我不明白。
  • 好的,但是为什么不能从 Control、Button 等继承并覆盖 Draw 在另一个程序集中对您不起作用?这是我不明白的部分。整个库(例如 FluentValidation)都建立在提供抽象类的基础上,这些抽象类可以在使用它们的应用程序中被覆盖。为什么您的特定用例无法实现?
  • 我需要将此程序集引用到我的 XamarinAndroid 项目。我可以为 xamarin 中的 Class Button 提供部分实现,以便以 xamarin 方式调用 Draw,就像有人需要以 WindowsForm 或 WPF 方式调用 Draw 时,它必须在那里实现,而不是由类库
  • 我现在要离开这个对话。尝试一下,这样你学得更快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多