Can't create delegate for DataAdapater.RowUpdated event (reflection)

T

Tim Werth

I am trying to use reflection to add an event handler for the RowUpdated
event of the OracleDataAdapter object (ODP.NET), but the same thing can be
said for SqlDataAdapter if you only use reflection. The code I supplied is
based on the SqlDataAdapter with reflection.

The error occurs when trying to create the delegate that will be passed in
to EventInfo.AddEventHandler. I get the following error:


An unhandled exception of type 'System.ArgumentException' occurred in
mscorlib.dll
Additional information: Error binding to target method.


The binding problem is with the second parameter to the event handler. It
is of type SqlRowUpdatedEventArgs. Again, in reality, I am trying to use
ODP.NET via reflection. So, in this example, I am not referencing the
System.Data or System.Data.Client namespace directly.

Without referencing the namespace, how would one declare a delegate's method
that has a parameter type that exists in a namespace not being referenced
(does that make sense?)?

I have included some sample code to illustrate the problem. The first
CreateDelegate will succeed with the using System.Data* lines *not*
commented out because you can use the SqlRowUpdatedEventArgs parameter. If
you comment out the "using System.Data" and "using System.Data.SqlClient"
lines, how do you create the delegate?

Again, I am illustrating my problem here using Sql types, because not
everyone has ODP.NET installed.

Tim

using System;

using System.Reflection;

// TAKE THE FOLLOWING TWO LINES OUT TO DEPEND SOLELY ON REFLECTION

using System.Data;

using System.Data.SqlClient;



namespace ReflectionEventTest

{

class Class1

{

[STAThread]

static void Main(string[] args)

{

CreateSqlDelegate();

}



static public void CreateSqlDelegate()

{

Module systemData = GetSystemDataModule();

Type t = systemData.GetType( "System.Data.SqlClient.SqlDataAdapter" );

object sqlDAObj = Activator.CreateInstance( t );

EventInfo ei = t.GetEvent( "RowUpdated" );

// This one works because the second parameter in the handler is of type
SqlRowUpdatedEventArgs

Delegate d1 = Delegate.CreateDelegate( ei.EventHandlerType, typeof(
Class1 ), "rowUpdated_ParamIsProperSql" );

// These other three produce the following error:

//

// An unhandled exception of type 'System.ArgumentException' occurred in
mscorlib.dll

//

// Additional information: Error binding to target method.

// Causes error

Delegate d2 = Delegate.CreateDelegate( ei.EventHandlerType, typeof(
Class1 ), "rowUpdated_ParamIsObject" );

// Causes error

Delegate d3 = Delegate.CreateDelegate( ei.EventHandlerType, typeof(
Class1 ), "rowUpdated_ParamIsBaseClass" );

// Causes error

Delegate d4 = Delegate.CreateDelegate( ei.EventHandlerType, typeof(
Class1 ), "rowUpdated_ParamIsIntPtr" );

}

// THIS WON'T COMPILE WHEN YOU TAKE THE using System.Data* LINES OUT AT THE
TOP

static private void rowUpdated_ParamIsProperSql(object sender,
SqlRowUpdatedEventArgs e)

{

}

static private void rowUpdated_ParamIsObject(object sender, object
oraRowUpdEventArgs)

{

}

// SqlRowUpdatedEventArgs is derived from
System.Data.Common.RowUpdatedEventArgs

static private void rowUpdated_ParamIsBaseClass(object sender,
System.Data.Common.RowUpdatedEventArgs e)

{

}

static private void rowUpdated_ParamIsIntPtr(object sender, System.IntPtr e)

{

}



static public Module GetSystemDataModule()

{

Assembly assembly = null;

Module module = null;

string strongName = "System.Data, PublicKeyToken=b77a5c561934e089,
Culture=neutral, Version=1.0.5000.0";

// Load the assembly

assembly = Assembly.Load( strongName );

// Get the module

module = assembly.GetModule( "System.Data.dll" );

return module;

}

}

}
 
K

Kevin Yu [MSFT]

Hi Tim,

First of all, I would like to confirm my understanding of your issue. From
your description, I understand that you cannot create a delegate throw
reflection. If there is any misunderstanding, please feel free to let me
know.

Based on my research, SqlRowUpdatedEventArgs contains enumeration values
StatementType. As this is not supported by current .NET Framework with
CreateDelegate, we cannot use it.

HTH.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
T

Tim Werth

Kevin,

Thanks for the reply, and if you say it can't be done because of a member of
SqlRowUpdatedEventArgs, I'll accept that. But, in general, I am still
curious as to the resolution of my problem in generic terms. Let me present
my problem another way without Sql or ODP.NET data types.

Suppose I have object O with and event E that are defined in a module M that
I am referencing in my code via reflection. M also defines object A which
is an argument to E. At compile-time, how can I have written code that will
create a delegate that uses A which the compiler knows nothing about?

Is there a way to bind the event delegate to a method with generic arguments
(object?) which, once called by the event, the method uses reflection to
work with the generic arguments (object?) to access their
properties/methods?

I noticed when using the reference that defines SqlRowUpdatedEventHandler
that it has an overloaded constructor. When adding a RowUpdated event with
System.Data.Client properly referenced, the code looks something like this:

SqlDataAdapter sda = new SqlDataAdapter(.....);

sda.RowUpdated += new SqlRowUpdatedEventHandler(sda_RowUpdated );

private static void sda_RowUpdated(object sender, SqlRowUpdatedEventArgs e)

{

}


But if you put your cursor anywhere in between the parentheses of the
SqlRowUpdatedEventHandler constructor and hit Ctrl-Shift-Space to bring up
IntelliSense, you can walk through its two constructors. The first
constructor takes a single argument like the code above illustrates, but the
second constructor takes two arguments, "object object, System.IntPtr
method".

Could the second constructor somehow be used when using reflection to define
the delegate?

Tim
 
K

Kevin Yu [MSFT]

Hi Tim,

As far as I know, currently, we don't have a workaround. Since you can use
another overload of constructor to create the delegate the reference to the
argument is still a SqlRowUpdatedEventArgs object which contains a
enumeration member which is not supported. Based on my research, the only
way to overcome this is make the enumeration value to be an integer. Sorry
for the inconvenience.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top