无论如何将扩展方法的结果存储在原始对象中?

Is there anyway to have the result of extension method stored in the original object?

我有一个 class UserControl class(说 MyDataGrid),它继承自第 3 方 DataGrid(说 TheirDataGrid)。在这种情况下,我只创建了 MyDataGrid 控件,但没有继承自 TheirDataGridColumn 和 TheirDataGridCell

的 MyDataGridColumn 和 MyDataGridCell

我的情况是,我为 TheirDataGridColumn 创建了一些扩展方法,这将向 TheirDataGridColumn 添加一些事件处理程序(通过 += 运算符)

如果我们只调用一次扩展方法就可以了 但是如果我们多次调用扩展方法,事件的数量就会累加起来。 (在我的例子中,它仍然可以,因为它只修改了事件中的一个原语属性,最后一个事件最终会生效。但仍然想知道是否有更好的方法)。

目前我能想到的有以下几种做法:

  1. 每次调用扩展方法时清除 TheirDataGridColumn 中的所有事件处理程序。但似乎我们只能通过反射来检索非公共变量(How to remove all event handlers from an event)。另外,在上面的例子中,它是众所周知的默认 Win 按钮控件,但我使用的是第 3 方控件。

  2. 有我自己的 MyDataGridColumn class,它继承自 TheirDataGridColumn,有一个额外的变量来存储添加的事件句柄。所以,每次我调用扩展函数(实际上,在这种情况下,不需要扩展函数,因为我们可以直接在 MyDataGridColumn class 中添加函数),它可以删除事件处理程序(通过 -= handler)。

  3. 有地方可以存储添加的事件处理程序,以便以后可以将其删除。但是由于我在扩展方法中,所以我没有办法保存添加的事件处理程序,因为没有扩展属性。如果我将它保存在另一个 class 的静态级别,它是静态级别而不是实例级别。当然,我可能有一个静态级别的字典,但需要考虑一个唯一的键来标识每一列。

对于 1,这是一种很肮脏的方式。此外,它可能会无意中删除一些其他事件处理程序

对于 2,它需要很多重构,我想避免这种情况

对于3,个人来说,我更喜欢这种方式,前提是我可以找到一种方法保存添加的事件处理程序,并在下次再次调用此方法时将其删除

非常感谢任何帮助。

更新代码,我们可以在添加处理程序之前删除它(因为如果没有处理程序,删除不会失败):

private void UltraGrid1_InitializeLayout(object sender, InitializeLayoutEventArgs e)
{
    var column = e.Layout.Bands[YOUR_BAND_INDEX].Columns[YOUR_COLUMN_INDEX];
    column.Style = Infragistics.Win.UltraWinGrid.ColumnStyle.URL;
    var editor = column.Editor as FormattedLinkEditor;

    //remove the handler before add, to prevent adding multiple handlers
    editor.LinkClicked -= this.Editor_LinkClicked;

    editor.LinkClicked += this.Editor_LinkClicked;
}

或者我们可以使用其中一个控件的 Tag 属性来记住我们已经为此添加了一个处理程序。 Windows 表单控件有一个 Tag 属性,它是一个对象,用于存储与控件关联的通用数据。如果我们在标签中存储一个字符串并稍后检查它,我们可以避免多次添加处理程序。也许像其中之一:

private void UltraGrid1_InitializeLayout(object sender, InitializeLayoutEventArgs e)
{
    var column = e.Layout.Bands[YOUR_BAND_INDEX].Columns[YOUR_COLUMN_INDEX];

    //did we add the handler already?
    if(column.Tag != null && column.Tag.ToString() == "handlerIsAdded")
      return;

    column.Style = Infragistics.Win.UltraWinGrid.ColumnStyle.URL;

    var editor = column.Editor as FormattedLinkEditor;
    editor.LinkClicked += this.Editor_LinkClicked;

    column.Tag = "handlerIsAdded"; //remember for next time, so we don't add handler again
}

不知道你是在专栏级别还是在编辑级别添加这个;我从未使用过您正在使用的网格控件。如果该列只有一个编辑器控件并且没有更新,那么您也可以使用编辑器控件:

private void UltraGrid1_InitializeLayout(object sender, InitializeLayoutEventArgs e)
{
    var column = e.Layout.Bands[YOUR_BAND_INDEX].Columns[YOUR_COLUMN_INDEX];
    column.Style = Infragistics.Win.UltraWinGrid.ColumnStyle.URL;
    var editor = column.Editor as FormattedLinkEditor;

    //did we add the handler already?
    if(editor.Tag != null && editor.Tag.ToString() == "handlerIsAdded")
      return;

    editor.LinkClicked += this.Editor_LinkClicked;

    editor.Tag = "handlerIsAdded"; //remember for next time
}