Coding a plug in and using LINQ:


Hi,

Few time ago I’ve created a post where I used LINQ to load  a plug in. At this time I have learned how to improve some aspects of this original idea. It’s possible to make a lot of improvements, however I’m only make a simple change.. However in my previous post I didn’t provided any code (only a couple of screen shots, so now I’ve the chance to add formatted code 😉 in wordpress ).

The following some notes about this sample:

  • I think it’s possible to use threads for loading the files, so it won’t freeze the application in order to load the files.
  • If you’re using .NET 3.5 on Windows, you might consider to use PLINQ (I’m not sure if it’s feasible).
  • The sample assumes that the concrete implementations of the plugins have a parameterless constructor.

Sample.CustomPlugin.Api is a dll project. This project contains the file IPluginInfo.cs.  It’s an interface that defines the contract that the plugins must implement. It is allocated in a separated dll project in order to distribute the contract to third parties.

using System;
namespace Sample.CustomPlugin.Api
{
 public interface IPluginInfo
 {
 string Name {get;}
 string Description {get;}
 }
}

Sample.CustomPlugin.Api.Apple and Sample.CustomPlugin.Api.Cherry are two separated dll projects. For each project there is a implementation of the Plugin contract.The implementations are ApplePlugin.cs and CherryPlugin.cs respectively.

<pre>using System;
using Sample.CustomPlugin.Api;

namespace Sample.CustomPlugin.Api.Apple
{
 public class ApplePlugin : IPluginInfo
 {
 public string  Name { get {return @"Apple tm"; }}
 public string Description {get {return @"This is the Apple plug in!";}}

 }
}

using System;
using Sample.CustomPlugin.Api;

namespace Sample.CustomPlugin.Api.Apple
{
 public class CherryPlugin : IPluginInfo
 {
 public string  Name { get {return @"Cherry OpenPlugin"; }}
 public string Description {get {return @"This is the Cherry OpenPlugin in!";}}

 }
}

Sample.CustomPlugin is the application project. This only references the Sample.CustomPlugin.Api project that defines the contract. The other two dlls will be loaded dynamically by the main application. These give us the chance of changing the implementation of the the others dlls without recompiling the entire application.

These is the main routine in charge of loading dynamically the dlls:

public static IEnumerable<IPluginType> PluginLoaderFor<IPluginType>(string pluginDirectory, string fileFilterPattern, bool hasToCheckIntoSubDirectories) {

	string interfaceName = typeof(IPluginType).Name;
	string[] files = null;

	fileFilterPattern = String.IsNullOrEmpty(fileFilterPattern) ? @"*.dll" : fileFilterPattern;
	pluginDirectory = Directory.Exists(pluginDirectory) ? pluginDirectory : Environment.CurrentDirectory;
	files = Directory.GetFiles(pluginDirectory,fileFilterPattern,hasToCheckIntoSubDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
#if DEBUG
Console.WriteLine(String.Format("Plugin Path Expression: {0}{1}.\nThere are {2} files has been found.",pluginDirectory,fileFilterPattern,files.Length));
#endif
	return
          from filename in files
	      where File.Exists(filename)
			  from type in Assembly.LoadFile(filename).GetTypes()
			  where type.IsClass && !type.IsAbstract && type.GetInterface(interfaceName) != null
			  select (IPluginType)Activator.CreateInstance(type);
}
public static void Main(string[] args)
{
	var plugins = PluginLoaderFor<IPluginInfo>(string.Empty,string.Empty,false);
#if DEBUG
	Console.WriteLine("There're {0} implementations for {1}", plugins.Count(), typeof(IPluginInfo).Name);
#endif
	if (plugins!=null)
		foreach (var pluginInfo in plugins)
			Console.WriteLine("PluginInfo Name: {0} Description: {1}", pluginInfo.Name,pluginInfo.Description);
	Console.ReadKey();
}

Today I was kinda bored so I decided to code this in monodevelop to see if it works as same as visual studio… and indeed it happened smoothly. Here is the source code for this sample: https://github.com/hmadrigal/playground-dotnet/tree/master/MsDotNet.PluginWithReflection Herberth


<pre>
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s