![]() CATEGORIES: BiologyChemistryConstructionCultureEcologyEconomyElectronicsFinanceGeographyHistoryInformaticsLawMathematicsMechanicsMedicineOtherPedagogyPhilosophyPhysicsPolicyPsychologySociologySportTourism |
Nbsp; Designing an Application That Supports Add-InsWhen you’re building extensible applications, interfaces should be the centerpiece. You could use a base class instead of an interface, but in general, an interface is preferred because it allows add-in de- velopers to choose their own base class. Suppose, for example, that you’re writing an application and you want others to be able to create types that your application can load and use seamlessly. Here’s the way to design this application:
■ Create a Host SDK assembly that defines an interface whose methods are used as the commu- nication mechanism between the host application and the add-in components. When defining the parameters and return types for the interface methods, try to use other interfaces or types defined in MSCorLib.dll. If you want to pass and return your own data types, define them in this Host SDK assembly, too. After you settle on your interface definitions, give this assembly a strong name (discussed in Chapter 3), and then package and deploy it to your partners and us- ers. Once published, you should really avoid making any kind of breaking changes to the types in this assembly. For example, do not change the interface in any way. However, if you define any data types, it is OK to add new members. If you make any modifications to the assembly, you’ll probably want to deploy it with a publisher policy file (also discussed in Chapter 3).
■ The add-in developers will, of course, define their own types in their own Add-In assembly. Their Add-In assembly will reference the types in your Host SDK assembly. The add-in devel- opers are able to put out a new version of their assembly as often as they’d like, and the host application will be able to consume the add-in types without any problem whatsoever. ■ Create a separate Host Application assembly containing your application’s types. This assem- bly will obviously reference the Host SDK assembly and use the types defined in it. Feel free to modify the code in the Host Application assembly to your heart’s desire. Because the add-in developers don’t reference the Host Application assembly, you can put out a new version of it every hour if you want to and not affect any of the add-in developers. This section contains some very important information. When using types across assemblies, you need to be concerned with assembly-versioning issues. Take your time to architect this cleanly by iso- lating the types that you use for communication across assembly boundaries into their own assembly. Avoid mutating or changing these type definitions. However, if you really need to modify the type definitions, make sure that you change the assembly’s version number and create a publisher policy file for the new version. I’ll now walk through a very simple scenario that puts all of this together. First, here is the code for the HostSDK.dll assembly.
using System;
namespace Wintellect.HostSDK { public interface IAddIn { String DoSomething(Int32 x); } }
Second, here is the code for an AddInTypes.dll assembly defining two public types that implement the HostSDK’s interface. To build this assembly, the HostSDK.dll assembly must be referenced.
using System; using Wintellect.HostSDK;
public sealed class AddIn_A : IAddIn { public AddIn_A() { } public String DoSomething(Int32 x) { return "AddIn_A: " + x.ToString(); } }
public sealed class AddIn_B : IAddIn { public AddIn_B() { } public String DoSomething(Int32 x) { return "AddIn_B: " + (x * 2).ToString(); } }
Third, here is the code for a simple Host.exe assembly (a console application). To build this as- sembly, the HostSDK.dll assembly must be referenced. To discover usable add-in types, this host code assumes that the types are defined in assemblies ending with a .dll file extension and that these as- semblies are deployed into the same directory as the host’s EXE file. Microsoft’s Managed Extensibility Framework (MEF) is built on top of the various mechanisms that I show here, and it also offers add-in registration and discovery mechanisms. I urge you to check MEF out if you are building a dynamically extensible application, because it can simplify some of the material in this chapter.
using System; using System.IO; using System.Reflection; using System.Collections.Generic; using Wintellect.HostSDK;
public static class Program { public static void Main() { // Find the directory that contains the Host exe String AddInDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
// Assume AddIn assemblies are in same directory as host's EXE file var AddInAssemblies = Directory.EnumerateFiles(AddInDir, "*.dll");
// Create a collection of AddIn Types usable by the host var AddInTypes = from file in AddInAssemblies let assembly = Assembly.Load(file) from t in assembly.ExportedTypes // Publiclyexported types // Type is usable if it is a class that implements IAddIn where t.IsClass && typeof(IAddIn).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo()) select t; // Initialization complete: the host has discovered the usable AddIns
// Here's how the host can construct AddIn objects and use them foreach (Type t in AddInTypes) { IAddIn ai = (IAddIn) Activator.CreateInstance(t); Console.WriteLine(ai.DoSomething(5)); } } }
The simple host/add-in scenario just shown doesn’t use AppDomains. However, in a real-life sce- nario, you will likely create each add-in in its own AppDomain with its own security and configuration settings. And of course, each AppDomain could be unloaded if you wanted to remove an add-in from memory. To communicate across the AppDomain boundary, you’d either tell the add-in developers to derive their add-in types from MarshalByRefObject or, more likely, have the host application define its own internal type that is derived from MarshalByRefObject. As each AppDomain is created, the host would create an instance of its own MarshalByRefObject-derived type in the new AppDomain. The host’s code (in the default AppDomain) would communicate with its own type (in the other App- Domains) to have it load add-in assemblies and create and use instances of the add-in types.
Date: 2016-03-03; view: 793
|