1

我目前正在开发一个允许连接到多个提供者特定数据库的程序,所以显然我正在使用非提供者特定类(在 System.Data.Common 中)来处理这些不同的连接,一旦连接或数据适配器已通过使用提供者的实现进行了实例化。

但是,我想利用根据 MSDN ( http://msdn.microsoft.com/en-us/library/6d1wk41s.aspx ) 被认为是 DataAdapter 基类的一部分的 RowUpdated 和 RowUpdating 事件。但显然情况并非如此,因为那些事件仅通过 DbDataAdapter 的提供者特定的实现(如 SqlDataAdapter、OleDbDataAdapter 等)来实现。

我的主要目标是能够通过使用通用的 DbDataAdapter 类来处理这些事件,并且必须将事情转换回数据适配器的特定于提供程序的实现的派生类将是一个很大的痛苦。

这样做有什么巧妙的想法吗?

4

2 回答 2

3

我在网上做了很多搜索,除了将实例重新转换回派生类以访问这些事件之外,真的没有找到任何具体的东西。

因此,通过使用扩展方法,我向 DbDataAdapter 抽象类添加了两个新方法,这将允许为这两个特定事件添加事件处理程序,这是我的实现(编辑于 2013 年 4 月 23 日,用于处理实例或静态处理程序方法):

using System;
using System.Data.Common;
using System.Reflection;

namespace Extensions
{
    /// <summary>
    /// Delegate event handler used with the <c>DbDataAdapter.RowUpdated</c> event.
    /// </summary>
    public delegate void RowUpdatedEventHandler(object sender, RowUpdatedEventArgs e);

    /// <summary>
    /// Delegate event handler used with the <c>DbDataAdapter.RowUpdating</c> event.
    /// </summary>
    public delegate void RowUpdatingEventHandler(object sender, RowUpdatingEventArgs e);

    public static class DbDataAdapterExtension
    {
        private static EventInfo GetEvent(string eventName, Type type)
        {
            return type.GetEvent(eventName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
        }

        /// <summary>
        /// Registers a <c>RowUpdatedEventHandler</c> with this instance's <c>RowUpdated</c> event.
        /// </summary>
        /// <param name="handler">The event handler to register for the event.</param>
        /// <returns><c>true</c> if the event handler was successfully registered, otherwise <c>false</c>.</returns>
        public static bool AddRowUpdatedHandler(this DbDataAdapter adapter, RowUpdatedEventHandler handler)
        {
            EventInfo updEvent = GetEvent("RowUpdated", adapter.GetType());

            if (updEvent != null)
            {
                try
                {
                    if (handler.Method.IsStatic)
                    {
                        updEvent.AddEventHandler(adapter, Delegate.CreateDelegate(updEvent.EventHandlerType, handler.Method));
                    }
                    else
                    {
                        updEvent.AddEventHandler(adapter, Delegate.CreateDelegate(updEvent.EventHandlerType, handler.Target, handler.Method));
                    }

                    return true;
                }
                catch { }
            }

            return false;
        }

        /// <summary>
        /// Registers a <c>RowUpdatingEventHandler</c> with this instance's <c>RowUpdating</c> event.
        /// </summary>
        /// <param name="handler">The event handler to register for the event.</param>
        /// <returns><c>true</c> if the event handler was successfully registered, otherwise <c>false</c>.</returns>
        public static bool AddRowUpdatingHandler(this DbDataAdapter adapter, RowUpdatingEventHandler handler)
        {
            EventInfo updEvent = GetEvent("RowUpdating", adapter.GetType());

            if (updEvent != null)
            {
                try
                {
                    if (handler.Method.IsStatic)
                    {
                        updEvent.AddEventHandler(adapter, Delegate.CreateDelegate(updEvent.EventHandlerType, handler.Method));
                    }
                    else
                    {
                        updEvent.AddEventHandler(adapter, Delegate.CreateDelegate(updEvent.EventHandlerType, handler.Target, handler.Method));
                    }

                    return true;
                }
                catch { }
            }

            return false;
        }
    }
}

我将基本 RowUpdatedEventArgs 和 RowUpdatingEventArgs 用于返回给委托的事件参数,因此如果您需要特定于提供程序的成员,这些成员只能通过从上述两个基本事件参数类派生的提供程序定义的类获得,然后他们将需要被强制转换为这些类。否则,它可以正常工作,现在我可以从 DbDataAdapter 类中获得独立于提供程序的事件处理程序(这是 Microsoft 应该从一开始就实现它们的方式)。

干杯!

于 2013-04-03T01:44:09.800 回答
0

谢谢 - 非常有用!

也许有人在 Visual Basic 中需要这个

例如这样称呼它:

Imports YourProject.DbDataAdapterExtension

. . .

Dim HandleOnRowUpd As RowUpdatedEventHandler = AddressOf OnRowUpdated

Dim TrueFalse As Boolean = YourDataAdapter.AddRowUpdatedHandler(HandleOnRowUpd)

Imports System.Data.Common
Imports System.Reflection
Imports System.Runtime.CompilerServices

' Namespace Extensions

''' <summary>
''' Delegate event handler used with the <c>DbDataAdapter.RowUpdated</c> event.
''' </summary>
''' 
Public Delegate Sub RowUpdatedEventHandler(sender As Object, e As RowUpdatedEventArgs)

''' <summary>
''' Delegate event handler used with the <c>DbDataAdapter.RowUpdating</c> event.
''' </summary>
''' 
Public Delegate Sub RowUpdatingEventHandler(sender As Object, e As RowUpdatingEventArgs)

Public Module DbDataAdapterExtension

    Sub New()
    End Sub

    Private Function GetEvent(eventName As String, type As Type) As EventInfo
        Return type.GetEvent(eventName, BindingFlags.[Public] Or BindingFlags.Instance Or BindingFlags.DeclaredOnly)
    End Function

    ''' <summary>
    ''' Registers a <c>RowUpdatedEventHandler</c> with this instance's <c>RowUpdated</c> event.
    ''' </summary>
    ''' <param name="handler">The event handler to register for the event.</param>
    ''' <returns><c>true</c> if the event handler was successfully registered, otherwise <c>false</c>.</returns>
    ''' 
    <Extension> Public Function AddRowUpdatedHandler(adapter As DbDataAdapter, handler As RowUpdatedEventHandler) As Boolean

        Dim updEvent As EventInfo = GetEvent("RowUpdated", adapter.[GetType]())

        If updEvent IsNot Nothing Then
            Try
                If handler.Method.IsStatic Then
                    updEvent.AddEventHandler(adapter, [Delegate].CreateDelegate(updEvent.EventHandlerType, handler.Method))
                Else
                    updEvent.AddEventHandler(adapter, [Delegate].CreateDelegate(updEvent.EventHandlerType, handler.Target, handler.Method))
                End If

                Return True
            Catch
            End Try
        End If

        Return False
    End Function

    ''' <summary>
    ''' Registers a <c>RowUpdatingEventHandler</c> with this instance's <c>RowUpdating</c> event.
    ''' </summary>
    ''' <param name="handler">The event handler to register for the event.</param>
    ''' <returns><c>true</c> if the event handler was successfully registered, otherwise <c>false</c>.</returns>
    ''' 
    <Extension> Public Function AddRowUpdatingHandler(adapter As DbDataAdapter, handler As RowUpdatingEventHandler) As Boolean

        Dim updEvent As EventInfo = GetEvent("RowUpdating", adapter.[GetType]())

        If updEvent IsNot Nothing Then
            Try
                If handler.Method.IsStatic Then
                    updEvent.AddEventHandler(adapter, [Delegate].CreateDelegate(updEvent.EventHandlerType, handler.Method))
                Else
                    updEvent.AddEventHandler(adapter, [Delegate].CreateDelegate(updEvent.EventHandlerType, handler.Target, handler.Method))
                End If

                Return True
            Catch
            End Try
        End If

        Return False
    End Function
End Module

' End Namespace
于 2015-04-22T23:43:38.153 回答