每次我开始在深C#项目中,我结束了大量的事件,真的只是需要通过一个单一项目。我坚持 EventHandler/EventArgs 实践中,但我喜欢什么要做的就是这样的:

public delegate void EventHandler<T>(object src, EventArgs<T> args);

public class EventArgs<T>: EventArgs {

  private T item;

  public EventArgs(T item) {
    this.item = item;
  }

  public T Item {
    get { return item; }
  }
}

后来,我可以拥有我

public event EventHandler<Foo> FooChanged;

public event EventHandler<Bar> BarChanged;

然而,似乎标准的。净是创建一个新的委派, EventArgs 类为每种类型的事件。是不是有什么错了我的一般方法?


编辑:因为这个职位是,我只是重新创造的这一个新的项目,并想要确定它是好。实际上,我是重新建立它作为我公布。我发现那有一个通用的 EventHandler<TEventArgs>, 所以你并不需要创建通用的委托人,但是你仍然需要一般 EventArgs<T> 类,因为 TEventArgs: EventArgs.
另一个编辑:一个缺点(对我)的内在的解决方案是额外的详细程度:

public event EventHandler<EventArgs<Foo>> FooChanged;

public event EventHandler<Foo> FooChanged;

它可以是一个痛苦的客户登记对你的事件,因为该系统名称空间是进口的默认,因此他们不得不手动找出你的名字空间,甚至有一个奇特的工具,如Resharper...任何人有任何想法有关?

有帮助吗?

解决方案

自.NET Framework 2.0

以来,已添加以下表单的委托
public delegate void EventHandler<TArgs>(object sender, TArgs args) where TArgs : EventArgs

您的方法更进一步,因为您为具有单个数据项的EventArgs提供了开箱即用的实现,但它缺少原始想法的几个属性:

  1. 您无法在不更改相关代码的情况下向事件数据添加更多属性。您必须更改委托签名以向事件订阅者提供更多数据。
  2. 您的数据对象是通用的,但它也是<!>“匿名<!>”;在阅读代码时,您必须解密<!> quot; Item <!> quot;使用财产。它应该根据它提供的数据命名。
  3. 当您具有底层(项目)类型的层次结构时,以这种方式使用泛型,您无法建立EventArgs的并行层次结构。例如。 EventArgs的LT <!>;碱基类型GT <!>;不是EventArgs <!> lt; DerivedType <!> gt;的基类型,即使BaseType是DerivedType的基础。
  4. 所以,我认为最好使用通用的EventHandler <!> lt; T <!> gt;,但仍然有自定义的EventArgs类,根据数据模型的要求进行组织。使用Visual Studio和ReSharper之类的扩展,创建新类只需要很少的命令。

其他提示

要使一般事件的《宣言》更加容易,我创造了一对夫妇的代码段。使用它们:

  • 拷贝的整个段。
  • 它贴在一个文本的文件(例如在记事本).
  • 保存文件。片断扩展。
  • 把。段文件在您的适当段的目录,例如:

Visual Studio2008年\代码段\视C#\,我的代码段

这是一个使用定制定引类与一种财产:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>Generic event with one type/argument.</Title>
            <Shortcut>ev1Generic</Shortcut>
            <Description>Code snippet for event handler and On method</Description>
            <Author>Kyralessa</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
        <Literal>
          <ID>type</ID>
          <ToolTip>Type of the property in the EventArgs subclass.</ToolTip>
          <Default>propertyType</Default>
        </Literal>
        <Literal>
          <ID>argName</ID>
          <ToolTip>Name of the argument in the EventArgs subclass constructor.</ToolTip>
          <Default>propertyName</Default>
        </Literal>
        <Literal>
          <ID>propertyName</ID>
          <ToolTip>Name of the property in the EventArgs subclass.</ToolTip>
          <Default>PropertyName</Default>
        </Literal>
        <Literal>
          <ID>eventName</ID>
          <ToolTip>Name of the event</ToolTip>
          <Default>NameOfEvent</Default>
        </Literal>
            </Declarations>
      <Code Language="CSharp"><![CDATA[public class $eventName$EventArgs : System.EventArgs
      {
        public $eventName$EventArgs($type$ $argName$)
        {
          this.$propertyName$ = $argName$;
        }

        public $type$ $propertyName$ { get; private set; }
      }

      public event EventHandler<$eventName$EventArgs> $eventName$;
            protected virtual void On$eventName$($eventName$EventArgs e)
            {
                var handler = $eventName$;
                if (handler != null)
                    handler(this, e);
            }]]>
      </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

这里是一个具有两个特性:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>Generic event with two types/arguments.</Title>
      <Shortcut>ev2Generic</Shortcut>
      <Description>Code snippet for event handler and On method</Description>
      <Author>Kyralessa</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>type1</ID>
          <ToolTip>Type of the first property in the EventArgs subclass.</ToolTip>
          <Default>propertyType1</Default>
        </Literal>
        <Literal>
          <ID>arg1Name</ID>
          <ToolTip>Name of the first argument in the EventArgs subclass constructor.</ToolTip>
          <Default>property1Name</Default>
        </Literal>
        <Literal>
          <ID>property1Name</ID>
          <ToolTip>Name of the first property in the EventArgs subclass.</ToolTip>
          <Default>Property1Name</Default>
        </Literal>
        <Literal>
          <ID>type2</ID>
          <ToolTip>Type of the second property in the EventArgs subclass.</ToolTip>
          <Default>propertyType1</Default>
        </Literal>
        <Literal>
          <ID>arg2Name</ID>
          <ToolTip>Name of the second argument in the EventArgs subclass constructor.</ToolTip>
          <Default>property1Name</Default>
        </Literal>
        <Literal>
          <ID>property2Name</ID>
          <ToolTip>Name of the second property in the EventArgs subclass.</ToolTip>
          <Default>Property2Name</Default>
        </Literal>
        <Literal>
          <ID>eventName</ID>
          <ToolTip>Name of the event</ToolTip>
          <Default>NameOfEvent</Default>
        </Literal>
      </Declarations>
      <Code Language="CSharp">
        <![CDATA[public class $eventName$EventArgs : System.EventArgs
      {
        public $eventName$EventArgs($type1$ $arg1Name$, $type2$ $arg2Name$)
        {
          this.$property1Name$ = $arg1Name$;
          this.$property2Name$ = $arg2Name$;
        }

        public $type1$ $property1Name$ { get; private set; }
        public $type2$ $property2Name$ { get; private set; }
      }

      public event EventHandler<$eventName$EventArgs> $eventName$;
            protected virtual void On$eventName$($eventName$EventArgs e)
            {
                var handler = $eventName$;
                if (handler != null)
                    handler(this, e);
            }]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

你可以遵循的模式创建他们的许多属性,因为你喜欢。

不,我不认为这是错误的做法。我认为它甚至可以在[精彩]一书框架设计指南中推荐。我做同样的事情。

这是正确的实施。它已被添加到.NET Framework(mscorlib),因为泛型首次出现(2.0)。

有关其使用和实现的更多信息,请参阅MSDN: http:// msdn .microsoft.com / EN-US /库/ db0etb8x.aspx

我第一次看到这个小图案时,我正在使用 DRY 规则的明智方式。

自.NET 2.0以来

  

EventHandler<T>

已经实施。

您可以在MSDN上找到Generic EventHandler http://msdn.microsoft。 COM / EN-US /库/ db0etb8x.aspx

我一直在广泛使用通用的EventHandler,并且能够阻止所谓的<!>“爆炸类型(类)<!>”; 项目保持较小,更容易导航。

为非通用的EventHandler委托提供新的直观委托是痛苦的,并且与现有类型重叠 附加<!>; * EventHandler <!>;在我看来,对新代表名称没什么帮助

我确实认为.NET的最新版本中只有这样的事件处理程序。就我而言,这是一个大拇指。

/ EDIT

最初没有得到区别。只要你传回一个继承自EventArgs的类,你就不会发现问题。如果由于可维护性原因而没有包装结果,我会担心。我仍然说它看起来不错。

使用通用事件处理程序实例

在.NET Framework 2.0之前,为了将自定义信息传递给事件处理程序,必须声明一个新的委托,指定从System.EventArgs类派生的类。这在.NET中不再适用

Framework 2.0,它引入了System.EventHandler <!> lt; T <!> gt;)委托。此通用委托允许从EventArgs派生的任何类与事件处理程序一起使用。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top