Late Binding to an Object Using Reflection

When the compiler encounters a reference when building an assembly, it loads the referenced assemblies and uses them to resolve all of the unresolved types. However, if you don't have the reference at compile time, you will not be able to call methods. You have just seen that with the classes in System.Reflection, you can dissect any assembly and find the methods and types in the assembly. It turns out that System.Reflection provides a means whereby a call can be made to a method in an assembly that is not known at compile time. This process is known as late binding.

It might be difficult to understand the usefulness of late binding at first, but some applications are not possible without a means of late binding. What if you wanted to provide feedback to third-party software? You don't know and don't want to know what the company will be doing with this feedback, but you want to provide a means whereby you can effectively notify them. You don't know ahead of time how many notifications you will have to set up. One solution would be to have a certain directory in which the third-party software would reside. You indicate to the developers of this third-party software that if they want to receive this notification, they will have to provide a function OutputMessage that takes as a single argument a string that contains the notification message. Now all you have to do is scan the directory and find out which of the software modules (probably DLLs) have an OutputMessage method defined and call the method. Using reflection, Listing 17.20 shows how this might be done with the .NET Framework. The complete source for this sample is in the LateBinding directory. Also included are two subprojects that build the required “first.dll” and “second.dll.” If you need to use a directory other than the two directories supplied, or if you don't want to use debug mode, you will need to change the source so that it can locate the two DLLs.

Listing 17.20. Late Binding Client
static void Main(string[] args)
{
    Assembly first = Assembly.LoadFrom(@"....Firstindebugfirst.dll");
    Assembly second = Assembly.LoadFrom(@"....Secondindebugsecond.dll");
    Assembly [] assemblies = new Assembly[] { first, second } ;
    foreach(Assembly a in assemblies)
    {
        Type[] types = a.GetTypes();
        foreach(Type t in types)
        {
            try
            {
                object o = Activator.CreateInstance(t);
                MethodInfo m = t.GetMethod("OutputMessage");
                m.Invoke(o, new object [] {"This is my message"} );
            }
            catch(Exception e)
            {
                Console.WriteLine(e);
            }
        }
    }
}

Notice that directory scanning code has not been included for clarity. An Assembly array is available that you can scan for the OutputMessage method. The key portion of the code is the three lines beginning with the Activator.CreateInstance call. The Activator.CreateInstance creates an instance of the type specified. Here that type will be the class containing the OutputMessage method. A search is performed for the OutputMessage method within the Type. The return for this scan is an instance of the MethodInfo class that corresponds to the OutputMessage method. The method is then called with a single string argument.

As you can imagine, late binding is pretty slow compared to compiled early bound code, but in some cases, the flexibility provided by late binding more than justifies the extra CPU cycles.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.23.30