Home Random Page


CATEGORIES:

BiologyChemistryConstructionCultureEcologyEconomyElectronicsFinanceGeographyHistoryInformaticsLawMathematicsMechanicsMedicineOtherPedagogyPhilosophyPhysicsPolicyPsychologySociologySportTourism






Nbsp;   Delegates and Reflection

So far in this chapter, the use of delegates has required the developer to know up front the prototype of the method that is to be called back. For example, if fb is a variable that references a Feedback delegate (see this chapter’s first program listing), to invoke the delegate, the code would look like the following.

 

fb(item); // item is defined as Int32

 

As you can see, the developer must know when coding how many parameters the callback method requires and the types of those parameters. Fortunately, the developer almost always has this infor- mation, so writing code like the preceding code isn’t a problem.

In some rare circumstances, however, the developer doesn’t have this information at compile time.

I showed an example of this in Chapter 11, “Events,” when I discussed the EventSet type. In this example, a dictionary maintained a set of different delegate types. At run time, to raise an event, one of the delegates was looked up in the dictionary and invoked. At compile time, it wasn’t possible to know exactly which delegate would be called and which parameters were necessary to pass to the delegate’s callback method.


Fortunately, System.Reflection.MethodInfo offers a CreateDelegate method that allows you to create a delegate when you just don’t have all the necessary information about the delegate at compile time. Here are the method overloads that MethodInfo defines.

 

public abstract class MethodInfo : MethodBase {

// Construct a delegate wrapping a static method.

public virtual Delegate CreateDelegate(Type delegateType);

 

// Construct a delegate wrapping an instance method; target refers to the ‘this’ argument. public virtual Delegate CreateDelegate(Type delegateType, Object target);

}

 

After you’ve created the delegate, you can call it by using Delegate’s DynamicInvoke method, which looks like the following.

 

public abstract class Delegate {

// Invoke a delegate passing it parameters

public Object DynamicInvoke(params Object[] args);

}

 

Using reflection APIs (discussed in Chapter 23, “Assembly Loading and Reflection”), you must first acquire a MethodInfo object referring to the method you want to create a delegate to. Then, you call the CreateDelegate method to have it construct a new object of a Delegate-derived type identi- fied by the first parameter, delegateType. If the delegate wraps an instance method, you will also pass to CreateDelegate a target parameter indicating the object that should be passed as the this parameter to the instance method.

System.Delegate’s DynamicInvoke method allows you to invoke a delegate object’s callback method, passing a set of parameters that you determine at run time. When you call DynamicInvoke, it internally ensures that the parameters you pass are compatible with the parameters the callback method expects. If they’re compatible, the callback method is called. If they’re not, an Argument­ Exception is thrown. DynamicInvoke returns the object the callback method returned.



The following code shows how to use the CreateDelegate and DynamicInvoke methods.

 

using System;

using System.Reflection; using System.IO;

 

 

// Here are some different delegate definitions internal delegate Object TwoInt32s(Int32 n1, Int32 n2); internal delegate Object OneString(String s1);

 

 

public static class DelegateReflection { public static void Main(String[] args) {

if (args.Length < 2) { String usage =

@"Usage:" +

"{0} delType methodName [Arg1] [Arg2]" +

"{0} where delType must be TwoInt32s or OneString" +


"{0} if delType is TwoInt32s, methodName must be Add or Subtract" + "{0} if delType is OneString, methodName must be NumChars or Reverse" + "{0}" +

"{0}Examples:" +

"{0} TwoInt32s Add 123 321" +

"{0} TwoInt32s Subtract 123 321" +

"{0} OneString NumChars \"Hello there\"" + "{0} OneString Reverse \"Hello there\"";

Console.WriteLine(usage, Environment.NewLine); return;

}

 

// Convert the delType argument to a delegate type Type delType = Type.GetType(args[0]);

if (delType == null) {

Console.WriteLine("Invalid delType argument: " + args[0]); return;

}

 

Delegate d; try {

// Convert the Arg1 argument to a method

MethodInfo mi = typeof(DelegateReflection).GetTypeInfo().GetDeclaredMethod(args[1]);

 

// Create a delegate object that wraps the static method d = mi.CreateDelegate(delType);

}

catch (ArgumentException) {

Console.WriteLine("Invalid methodName argument: " + args[1]); return;

}

 

// Create an array that that will contain just the arguments

// to pass to the method via the delegate object Object[] callbackArgs = new Object[args.Length ­ 2];

 

if (d.GetType() == typeof(TwoInt32s)) { try {

// Convert the String arguments to Int32 arguments for (Int32 a = 2; a < args.Length; a++)

callbackArgs[a ­ 2] = Int32.Parse(args[a]);

}

catch (FormatException) { Console.WriteLine("Parameters must be integers."); return;

}

}

 

if (d.GetType() == typeof(OneString)) {

// Just copy the String argument

Array.Copy(args, 2, callbackArgs, 0, callbackArgs.Length);

}


try {

// Invoke the delegate and show the result Object result = d.DynamicInvoke(callbackArgs); Console.WriteLine("Result = " + result);

}

catch (TargetParameterCountException) { Console.WriteLine("Incorrect number of parameters specified.");

}

}

 

 

// This callback method takes 2 Int32 arguments private static Object Add(Int32 n1, Int32 n2) {

return n1 + n2;

}

 

// This callback method takes 2 Int32 arguments private static Object Subtract(Int32 n1, Int32 n2) {

return n1 ­ n2;

}

 

// This callback method takes 1 String argument private static Object NumChars(String s1) {

return s1.Length;

}

 

// This callback method takes 1 String argument private static Object Reverse(String s1) {

return new String(s1.Reverse().ToArray());

}

}


 


C HA P T E R 1 8

Custom Attributes

In this chapter:

Using Custom Attributes......................................................................... 421

Defining Your Own Attribute Class.......................................................... 425

Attribute Constructor and Field/Property Data Types............................. 428

Detecting the Use of a Custom Attribute................................................ 430

Matching Two Attribute Instances Against Each Other............................ 434


Date: 2016-03-03; view: 790


<== previous page | next page ==>
Nbsp;   C#’s Syntactical Sugar for Delegates | Nbsp;   Using Custom Attributes
doclecture.net - lectures - 2014-2024 year. Copyright infringement or personal data (0.008 sec.)