1

我有一个想要构建的控件框架的概念。这个想法的不同之处在于,我不打算采用“一刀切”的方法或“一个控制来统治他们”的方法。

例如,Telerik 和 ComponentOne、Xceed 等制作了一个非常棒的 Grid 控件。然而,它们都是具有成百上千个方法和属性、复杂对象模型层次结构等的巨大控件……这些往往网格对于您需要的东西来说太过分了,但是您仍然必须承担学习整个网格以做一些简单的事情的艰巨任务。

我的概念更像是一种“混合”方法。您可以在其中创建一个非常简单的控件,然后构建您可以“添加”到该控件的功能点菜。例如,您有一个简单的网格,并且您想为每个添加带有页眉和页脚的网格“部分”。

好的,那么问题出在哪里?做这种事情的传统方式是通过多重继承,C# 不支持。即使它确实支持它,我仍然认为 MI 增加的问题多于它解决的问题。

所以我正在征求关于如何解决这个问题的意见。MEF 会是一个潜在的解决方案吗?

编辑:

我想到的是,可以使用表达式树从各种表达式构建控件。我必须再考虑一下,但这是一个有趣的概念。

另一个可能的选项可能是“控制生成器”,它基于选定的特征生成装配。这似乎更复杂,但使用 T4 可能是可以管理的。

4

6 回答 6

3

几个选项

  1. 考虑装饰器模式;扩展您可以在运行时构建的极简类的行为的小对象。Dotnet 框架中的典型示例是围绕 IO 流(例如 StreamReader/Writer、TextStreamReader/Writer、FileStreamReader/Writer);它在 OO UI 框架中也很常见,典型的例子看起来像var window=new HorizontalScrollingWindowDecorator(new VerticalScrollingWindowDecorator(new Window));

  2. 状态、策略、命令和复合模式为处理行为组合提供了各种替代方案,而无需大量控制流。例如,您将某些类型的行为委托给对象的当前状态(您的某些类方法基本上调用当前对象状态的方法)。您还可以将行为委托给命令对象,或使用复合命令构建复杂命令。单继承通常会导致您更喜欢对象的组合而不是继承,这些都是组合行为的经典模式,适用于单继承。

  3. 当某些小行为需要由特定实例实现时,您可以将委托用于函数式编程中常见的“中间孔”模式。

  4. 您可以使用 PostSharp 或类似的面向方面的编程工具来执行运行时或编译时的行为编织,这对于几个不同类所需的行为与该类的主要职责没有太大关系的情况特别有用。

于 2010-12-01T18:01:37.320 回答
2

就个人而言,我认为多重继承无论如何都是实现这种设计的不好方法。大多数时候,多重继承似乎是一个糟糕的设计。继承远远僵化了组件之间的关系。

组合要灵活得多,在这种情况下,MEF 将是一个很好的起点。

您的控件的基类将是一个行为容器——本质上是一个 MEF 容器。

它仍然留下了其他类如何与您的控件交互的问题。有很多选择。例如基础控件上的标准接口、消息传递,甚至在 C# 4.0 中使用动态绑定。

于 2010-12-01T17:51:17.010 回答
1

我想尝试回答而不评论这是否是一个值得解决的问题。

我没有为组件尝试过这个,但理论上有装饰器模式:您可以在运行时添加插件来拦截控件的(键盘和鼠标)输入和(屏幕)输出。

于 2010-12-01T17:45:02.097 回答
1

WPF 通过允许您将逻辑元素的可视化表示与数据模板组合来解决此问题。Control 类本身不是通过混合功能来创建新的 Control 类,而是通过合并各种类型的 Content 的能力提供扩展点,并使用丰富的模板系统来排列和可视化 Content。

换句话说,仍然可以说是“一个控制来统治一切”,但控制是一个骨架,而不是一个完整的身体。脚手架提供了一个易于理解的框架,可以在其中添加功能,模板系统提供了充实控件部分的粘合剂。


关于 MEF,MEF 给你的是扩展代码的发现和注入。它很有价值,但不能直接解决您描述的问题。您的问题与代码的发现关系不大,而与如何组合代码以创建连贯的整体控制的机制有关。MEF 有助于执行一些粘合,但它只是问题的一小部分。

于 2010-12-01T17:49:10.720 回答
0

你想构建一个插件类型的框架吗?我肯定会向您介绍托管可扩展性框架。可以在带有 WinForms 或 WPF 的 .Net 4.0 中使用。

于 2010-12-01T17:50:41.080 回答
0

如果您对已经实现 mixins 的框架感兴趣以供参考,请查看 re-motion 框架 (https://www.re-motion.org/)。令人惊讶的是,在这个框架中可以轻松实现 mixins,

以下是“Hello World”级别的参考应用程序。

使用从网站下载的程序集,在 VS2010 中创建一个类库和一个控制台应用程序,在两个项目中添加对程序集 remotion.dll 和 remotion.interfaces.dll 的引用。

using System;

namespace Domain
{
  public class Person
  {
    public Person()
    {
    }
    public Person(Person person)
    {
      FirstName = person.FirstName;
      LastName = person.LastName;
      BirthDay = person.BirthDay;
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDay { get; set; }
  }
}



using System;
using Remotion.Mixins;

namespace Domain
{
  public interface IEmployeeMixin
  {
    int Salary { get; set; }
    DateTime? HireDate { get; set; }
  }

  [Extends(typeof(Person))]
  public class EmployeeMixin : IEmployeeMixin
  {
    public int Salary { get; set;  }
    public DateTime? HireDate { get; set;}
    public EmployeeMixin()
    {
      // set default values
      Salary = 1000;
      HireDate = DateTime.Now;
    }
  }
}



using Domain;
using Remotion.Reflection;
using Remotion.Mixins;

namespace ConsoleApp
{
  class Program
  {
    static void Main(string[] args)
    {
      Person p = new Person();
      p.FirstName = "John";
      p.LastName = "Doe";

      var employee = (IEmployeeMixin)ObjectFactory.Create<Person>(ParamList.Create(p));

      System.Console.WriteLine("Fullname: {0}", ((Person)employee).FirstName + " " + ((Person)employee).LastName);
      System.Console.WriteLine("Salary: {0}", employee.Salary);

      System.Console.ReadKey();
    }
  }
}

基于这个参考实现,应该很容易理解这个mixin是如何在这个框架中实现的。如果您想获得有关此框架(它是一个完整的 DDD 开发框架)或 mixins 的更多信息,请不要犹豫。我可以为您提供更多文档。

斯特凡

于 2011-01-11T13:45:40.643 回答