From c9b20cd2cd792e9aec589cf33a64c6d1ef916ac2 Mon Sep 17 00:00:00 2001 From: Markus Ewald Date: Sun, 11 Mar 2012 08:57:24 +0000 Subject: [PATCH] Moved plugin framework into its own assembly (it's really not such a good idea anymore with the Managed Extensibility Framework and all); added Xbox360 and Windows Phone 7 projects for Nuclex.Support.Transactions git-svn-id: file:///srv/devel/repo-conversion/nusu@275 d2e56fa2-650e-0410-a79f-9358c0239efd --- Nuclex.Support (net-4.0).csproj | 34 --- Nuclex.Support (xna-4.0-phone7).csproj | 34 --- Nuclex.Support (xna-4.0-xbox360).csproj | 34 --- Source/Plugins/AssemblyLoadEventArgs.Test.cs | 51 ----- Source/Plugins/AssemblyLoadEventArgs.cs | 57 ----- Source/Plugins/Employer.Test.cs | 92 -------- Source/Plugins/Employer.cs | 48 ---- Source/Plugins/FactoryEmployer.Test.cs | 169 -------------- Source/Plugins/FactoryEmployer.cs | 125 ----------- Source/Plugins/IAbstractFactory.cs | 51 ----- Source/Plugins/IAssemblyLoader.cs | 40 ---- Source/Plugins/InstanceEmployer.Test.cs | 155 ------------- Source/Plugins/InstanceEmployer.cs | 80 ------- Source/Plugins/NoPluginAttribute.Test.cs | 46 ---- Source/Plugins/NoPluginAttribute.cs | 38 ---- Source/Plugins/PluginHost.Test.cs | 168 -------------- Source/Plugins/PluginHost.cs | 121 ---------- Source/Plugins/PluginRepository.Test.cs | 222 ------------------- Source/Plugins/PluginRepository.cs | 193 ---------------- Source/Plugins/PrototypeFactory.Test.cs | 141 ------------ Source/Plugins/PrototypeFactory.cs | 58 ----- 21 files changed, 1957 deletions(-) delete mode 100644 Source/Plugins/AssemblyLoadEventArgs.Test.cs delete mode 100644 Source/Plugins/AssemblyLoadEventArgs.cs delete mode 100644 Source/Plugins/Employer.Test.cs delete mode 100644 Source/Plugins/Employer.cs delete mode 100644 Source/Plugins/FactoryEmployer.Test.cs delete mode 100644 Source/Plugins/FactoryEmployer.cs delete mode 100644 Source/Plugins/IAbstractFactory.cs delete mode 100644 Source/Plugins/IAssemblyLoader.cs delete mode 100644 Source/Plugins/InstanceEmployer.Test.cs delete mode 100644 Source/Plugins/InstanceEmployer.cs delete mode 100644 Source/Plugins/NoPluginAttribute.Test.cs delete mode 100644 Source/Plugins/NoPluginAttribute.cs delete mode 100644 Source/Plugins/PluginHost.Test.cs delete mode 100644 Source/Plugins/PluginHost.cs delete mode 100644 Source/Plugins/PluginRepository.Test.cs delete mode 100644 Source/Plugins/PluginRepository.cs delete mode 100644 Source/Plugins/PrototypeFactory.Test.cs delete mode 100644 Source/Plugins/PrototypeFactory.cs diff --git a/Nuclex.Support (net-4.0).csproj b/Nuclex.Support (net-4.0).csproj index 36d30b0..660485c 100644 --- a/Nuclex.Support (net-4.0).csproj +++ b/Nuclex.Support (net-4.0).csproj @@ -223,40 +223,6 @@ CommandLine.cs - - - AssemblyLoadEventArgs.cs - - - - Employer.cs - - - FactoryEmployer.cs - - - - PrototypeFactory.cs - - - - InstanceEmployer.cs - - - - - - - NoPluginAttribute.cs - - - - PluginHost.cs - - - - PluginRepository.cs - PropertyChangedEventArgsHelper.cs diff --git a/Nuclex.Support (xna-4.0-phone7).csproj b/Nuclex.Support (xna-4.0-phone7).csproj index b6d1d9f..e69b7cb 100644 --- a/Nuclex.Support (xna-4.0-phone7).csproj +++ b/Nuclex.Support (xna-4.0-phone7).csproj @@ -254,40 +254,6 @@ CommandLine.cs - - - AssemblyLoadEventArgs.cs - - - - Employer.cs - - - FactoryEmployer.cs - - - - PrototypeFactory.cs - - - - InstanceEmployer.cs - - - - - - - NoPluginAttribute.cs - - - - PluginHost.cs - - - - PluginRepository.cs - PropertyChangedEventArgsHelper.cs diff --git a/Nuclex.Support (xna-4.0-xbox360).csproj b/Nuclex.Support (xna-4.0-xbox360).csproj index b20a931..39fab7a 100644 --- a/Nuclex.Support (xna-4.0-xbox360).csproj +++ b/Nuclex.Support (xna-4.0-xbox360).csproj @@ -265,40 +265,6 @@ CommandLine.cs - - - AssemblyLoadEventArgs.cs - - - - Employer.cs - - - FactoryEmployer.cs - - - - PrototypeFactory.cs - - - - InstanceEmployer.cs - - - - - - - NoPluginAttribute.cs - - - - PluginHost.cs - - - - PluginRepository.cs - PropertyChangedEventArgsHelper.cs diff --git a/Source/Plugins/AssemblyLoadEventArgs.Test.cs b/Source/Plugins/AssemblyLoadEventArgs.Test.cs deleted file mode 100644 index 81a9f56..0000000 --- a/Source/Plugins/AssemblyLoadEventArgs.Test.cs +++ /dev/null @@ -1,51 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -#if UNITTEST - -using System; -using System.IO; -using System.Reflection; - -using NUnit.Framework; - -namespace Nuclex.Support.Plugins { - - /// Unit Test for the assembly load event argument container - [TestFixture] - internal class AssemblyLoadEventArgsTest { - - /// - /// Tests whether the argument container correctly stores an assembly reference - /// - [Test] - public void TestEmployerDefaultConstructorDetection() { - Assembly assembly = Assembly.GetExecutingAssembly(); - - AssemblyLoadEventArgs testArguments = new AssemblyLoadEventArgs(assembly); - - Assert.AreSame(assembly, testArguments.LoadedAssembly); - } - - } - -} // namespace Nuclex.Support.Plugins - -#endif // UNITTEST diff --git a/Source/Plugins/AssemblyLoadEventArgs.cs b/Source/Plugins/AssemblyLoadEventArgs.cs deleted file mode 100644 index bc73c14..0000000 --- a/Source/Plugins/AssemblyLoadEventArgs.cs +++ /dev/null @@ -1,57 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace Nuclex.Support.Plugins { - -#if XBOX360 || WINDOWS_PHONE - - /// Signature for the AssemblyLoad event - /// Object that is reporting that an assembly was loaded - /// Contains the loaded assembly - public delegate void AssemblyLoadEventHandler( - object sender, AssemblyLoadEventArgs arguments - ); - - /// Argument container for the AssemblyLoad event arguments - public class AssemblyLoadEventArgs : EventArgs { - - /// Initializes a new event argument container - /// Assembly that has been loaded - public AssemblyLoadEventArgs(Assembly loadedAssembly) { - this.loadedAssembly = loadedAssembly; - } - - /// Assembly that was loaded by the sender of the event - public Assembly LoadedAssembly { - get { return this.loadedAssembly; } - } - - /// Loaded assembly that will be provided to the event receivers - private Assembly loadedAssembly; - - } - -#endif // XBOX360 || WINDOWS_PHONE - -} // namespace Nuclex.Support.Plugins diff --git a/Source/Plugins/Employer.Test.cs b/Source/Plugins/Employer.Test.cs deleted file mode 100644 index a7a1b0c..0000000 --- a/Source/Plugins/Employer.Test.cs +++ /dev/null @@ -1,92 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -#if UNITTEST - -using System; -using System.IO; - -using NUnit.Framework; - -namespace Nuclex.Support.Plugins { - - /// Unit Test for the employer class - [TestFixture] - internal class EmployerTest { - - #region class TestEmployer - - /// Dummy implementation for testing the employer class - private class TestEmployer : Employer { - - /// Employs the specified plugin type - /// Type to be employed - public override void Employ(Type type) { } - - } - - #endregion // class TestEmployer - - #region class NoDefaultConstructor - - /// Test class that doesn't have a default constructor - private class NoDefaultConstructor { - /// Initializes a new instance of the test class - /// Dummy argument so this is no default constructor - public NoDefaultConstructor(int dummy) { } - } - - #endregion // class NoDefaultConstructor - - #region class NonPublicDefaultConstructor - - /// Test class that has a non-public default constructor - private class NonPublicDefaultConstructor { - /// Initializes a new instance of the test class - protected NonPublicDefaultConstructor() { } - } - - #endregion // class NonPublicDefaultConstructor - - #region class PublicDefaultConstructor - - /// Test class that has a public default constructor - private class PublicDefaultConstructor { - /// Initializes a new instance of the test class - public PublicDefaultConstructor() { } - } - - #endregion // class PublicDefaultConstructor - - /// Tests whether the employer can detect a default constructor - [Test] - public void TestEmployerDefaultConstructorDetection() { - TestEmployer testEmployer = new TestEmployer(); - - Assert.IsFalse(testEmployer.CanEmploy(typeof(NoDefaultConstructor))); - Assert.IsFalse(testEmployer.CanEmploy(typeof(NonPublicDefaultConstructor))); - Assert.IsTrue(testEmployer.CanEmploy(typeof(PublicDefaultConstructor))); - } - - } - -} // namespace Nuclex.Support.Plugins - -#endif // UNITTEST diff --git a/Source/Plugins/Employer.cs b/Source/Plugins/Employer.cs deleted file mode 100644 index 57f450f..0000000 --- a/Source/Plugins/Employer.cs +++ /dev/null @@ -1,48 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; - -namespace Nuclex.Support.Plugins { - - /// Plugin type employer - /// - /// This class is used by the plugin host to assess whether a concrete type found - /// in a plugin assembly is suited to be processed the plugin user. If so, - /// the employer can employ the type. Employing can typically mean to create an - /// instance of the type in the plugin assembly or to build a runtime-factory - /// that can create instances of the type when it is needed. - /// - public abstract class Employer { - - /// Determines whether the type suites the employer's requirements - /// Type which will be assessed - /// True if the type can be employed, otherwise false - public virtual bool CanEmploy(Type type) { - return type.HasDefaultConstructor(); - } - - /// Employs the specified plugin type - /// Type to be employed - public abstract void Employ(Type type); - - } - -} // namespace Nuclex.Support.Plugins diff --git a/Source/Plugins/FactoryEmployer.Test.cs b/Source/Plugins/FactoryEmployer.Test.cs deleted file mode 100644 index 08f9dd5..0000000 --- a/Source/Plugins/FactoryEmployer.Test.cs +++ /dev/null @@ -1,169 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; -using System.IO; - -#if UNITTEST - -using NUnit.Framework; - -namespace Nuclex.Support.Plugins { - - /// Unit Test for the factory employer class - [TestFixture] - internal class FactoryEmployerTest { - - #region class Base - - /// - /// Abstract base class to serve as abstract product for testing the factory employer - /// - private abstract class Base { } - - #endregion // class Base - - #region class Derived - - /// - /// Class derived from the abstract base to serve as concrete product for - /// testing the factory employer - /// - private class Derived : Base { } - - #endregion // class Derived - - #region class GenericDerived - - /// - /// Generic class derived from the abstract base to serve as concrete product - /// for testing the factory employer - /// - private class GenericDerived : Base { } - - #endregion // class GenericDerived - - #region class Unrelated - - /// Unrelated class used to test the factory employer - private class Unrelated { } - - #endregion // class Unrelated - - /// - /// Tests whether the factory employer can detect employable types - /// - [Test] - public void TestCanEmploy() { - FactoryEmployer testEmployer = new FactoryEmployer(); - - Assert.IsFalse(testEmployer.CanEmploy(typeof(Base))); - Assert.IsTrue(testEmployer.CanEmploy(typeof(Derived))); - Assert.IsFalse(testEmployer.CanEmploy(typeof(Unrelated))); - } - - /// - /// Tests whether the factory employer can use the non-generic IAbstractFactory - /// interface instead of its generic variant - /// - [Test] - public void TestNonGenericCreateInstance() { - FactoryEmployer testEmployer = new FactoryEmployer(); - testEmployer.Employ(typeof(Derived)); - - Assert.That(testEmployer.Factories.Count, Is.AtLeast(1)); - - IAbstractFactory factory = testEmployer.Factories[0] as IAbstractFactory; - Assert.IsNotNull(factory); - - Assert.IsInstanceOf(factory.CreateInstance()); - } - - /// - /// Tests whether the factory employer throws an exception when it is asked to - /// employ an abstract class - /// - [Test] - public void TestThrowOnEmployAbstractClass() { - FactoryEmployer testEmployer = new FactoryEmployer(); - - Assert.Throws( - delegate() { testEmployer.Employ(typeof(Base)); } - ); - } - - /// - /// Tests whether the factory employer throws an exception when it is asked to - /// employ a class that is not the product type or a derivative thereof - /// - [Test] - public void TestThrowOnEmployUnrelatedClass() { - FactoryEmployer testEmployer = new FactoryEmployer(); - - Assert.Throws( - delegate() { testEmployer.Employ(typeof(Unrelated)); } - ); - } - - /// - /// Tests whether the factory employer throws an exception when it is asked to - /// employ a class that requires generic parameters for instantiation - /// - [Test] - public void TestThrowOnEmployGenericClass() { - FactoryEmployer testEmployer = new FactoryEmployer(); - - Assert.Throws( - delegate() { testEmployer.Employ(typeof(GenericDerived<>)); } - ); - } - - /// - /// Tests whether the factory employer can employ a class derived from the product - /// - [Test] - public void TestEmployClassDerivedFromProduct() { - FactoryEmployer testEmployer = new FactoryEmployer(); - - testEmployer.Employ(typeof(Derived)); - - Assert.AreEqual(1, testEmployer.Factories.Count); - Assert.IsInstanceOf(testEmployer.Factories[0].CreateInstance()); - } - - /// - /// Tests whether the factory employer can employ the product class itself if it - /// isn't abstract - /// - [Test] - public void TestEmployProduct() { - FactoryEmployer testEmployer = new FactoryEmployer(); - - testEmployer.Employ(typeof(Unrelated)); - - Assert.AreEqual(1, testEmployer.Factories.Count); - Assert.IsInstanceOf(testEmployer.Factories[0].CreateInstance()); - } - - } - -} // namespace Nuclex.Support.Plugins - -#endif // UNITTEST diff --git a/Source/Plugins/FactoryEmployer.cs b/Source/Plugins/FactoryEmployer.cs deleted file mode 100644 index f5b11c0..0000000 --- a/Source/Plugins/FactoryEmployer.cs +++ /dev/null @@ -1,125 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; -using System.Collections.Generic; - -namespace Nuclex.Support.Plugins { - - /// Employer to create factories of suiting types found in plugins - /// - /// Interface or base class that the types need to implement - /// - /// - /// - /// This employer will not directly instanciate any compatible types found in - /// plugin assemblies, but generated runtime-factories of these types, enabling the - /// user to decide when and how many instances of a type will be created. - /// - /// - /// This approach has the advantage that it enables even assemblies that were not - /// intended to be plugins can be loaded as plugins, without risking an instanciation - /// or complex and possibly heavy-weight types. The disadvantage is that the - /// runtime-factory can not provide decent informationa about the plugin type like - /// a human-readable name, capabilities or an icon. - /// - /// - public class FactoryEmployer : Employer where TProduct : class { - - #region class ConcreteFactory - - /// Concrete factory for the types in a plugin assembly - private class ConcreteFactory : IAbstractFactory, IAbstractFactory { - - /// - /// Initializes a factory and configures it for the specified product - /// - /// Type of which the factory creates instances - public ConcreteFactory(Type type) { - this.concreteType = type; - } - - /// Create a new instance of the type the factory is configured to - /// The newly created instance - public TProduct CreateInstance() { - return (TProduct)Activator.CreateInstance(this.concreteType); - } - - /// Create a new instance of the type the factory is configured to - /// The newly created instance - object IAbstractFactory.CreateInstance() { - return Activator.CreateInstance(this.concreteType); - } - - /// Concrete product which the factory instance creates - private Type concreteType; - - } - - #endregion // class Factory - - /// Initializes a new FactoryEmployer - public FactoryEmployer() { - this.employedFactories = new List>(); - } - - /// List of all factories that the instance employer has created - public List> Factories { - get { return this.employedFactories; } - } - - /// Determines whether the type suites the employer's requirements - /// Type which will be assessed - /// True if the type can be employed - public override bool CanEmploy(Type type) { - return - type.HasDefaultConstructor() && - typeof(TProduct).IsAssignableFrom(type) && - !type.ContainsGenericParameters; - } - - /// Employs the specified plugin type - /// Type to be employed - public override void Employ(Type type) { - if(!type.HasDefaultConstructor()) { - throw new MissingMethodException( - "Cannot employ type because it does not have a public default constructor" - ); - } - if(!typeof(TProduct).IsAssignableFrom(type)) { - throw new InvalidCastException( - "Cannot employ type because it cannot be cast to the factory's product type" - ); - } - if(type.ContainsGenericParameters) { - throw new ArgumentException( - "Cannot employ type because it requires generic parameters", "type" - ); - } - - this.employedFactories.Add(new ConcreteFactory(type)); - } - - /// All factories that the instance employer has created - private List> employedFactories; - - } - -} // namespace Nuclex.Support.Plugins diff --git a/Source/Plugins/IAbstractFactory.cs b/Source/Plugins/IAbstractFactory.cs deleted file mode 100644 index 8165865..0000000 --- a/Source/Plugins/IAbstractFactory.cs +++ /dev/null @@ -1,51 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; -using System.Collections.Generic; - -namespace Nuclex.Support.Plugins { - - /// Abstract factory for a concrete type - public interface IAbstractFactory { - - /// - /// Creates a new instance of the type to which the factory is specialized - /// - /// The newly created instance - object CreateInstance(); - - } - - /// Abstract factory for a concrete type - /// - /// Interface or base class of the product of the factory - /// - public interface IAbstractFactory { - - /// - /// Creates a new instance of the type to which the factory is specialized - /// - /// The newly created instance - ProductType CreateInstance(); - - } - -} // namespace Nuclex.Support.Plugins diff --git a/Source/Plugins/IAssemblyLoader.cs b/Source/Plugins/IAssemblyLoader.cs deleted file mode 100644 index 5e12bc6..0000000 --- a/Source/Plugins/IAssemblyLoader.cs +++ /dev/null @@ -1,40 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace Nuclex.Support.Plugins { - - /// Interface for an assembly loading helper - public interface IAssemblyLoader { - - /// Tries to loads an assembly from a file - /// Path to the file that is loaded as an assembly - /// - /// Output parameter that receives the loaded assembly or null - /// - /// True if the assembly was loaded successfully, otherwise false - bool TryLoadFile(string path, out Assembly loadedAssembly); - - } - -} // namespace Nuclex.Support.Plugins diff --git a/Source/Plugins/InstanceEmployer.Test.cs b/Source/Plugins/InstanceEmployer.Test.cs deleted file mode 100644 index ab24d28..0000000 --- a/Source/Plugins/InstanceEmployer.Test.cs +++ /dev/null @@ -1,155 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; -using System.IO; - -#if UNITTEST - -using NUnit.Framework; - -namespace Nuclex.Support.Plugins { - - /// Unit Test for the instance employer class - [TestFixture] - internal class InstanceEmployerTest { - - #region class Base - - /// - /// Abstract base class to serve as abstract product for testing the instance employer - /// - private abstract class Base { } - - #endregion // class Base - - #region class Derived - - /// - /// Class derived from the abstract base to serve as concrete product for - /// testing the instance employer - /// - private class Derived : Base { } - - #endregion // class Derived - - #region class GenericDerived - - /// - /// Generic class derived from the abstract base to serve as concrete product - /// for testing the instance employer - /// - private class GenericDerived : Base { } - - #endregion // class GenericDerived - - #region class Unrelated - - /// Unrelated class used to test the instance employer - private class Unrelated { } - - #endregion // class Unrelated - - /// - /// Tests whether the instance employer can detect employable types - /// - [Test] - public void TestCanEmploy() { - InstanceEmployer testEmployer = new InstanceEmployer(); - - Assert.IsFalse(testEmployer.CanEmploy(typeof(Base))); - Assert.IsTrue(testEmployer.CanEmploy(typeof(Derived))); - Assert.IsFalse(testEmployer.CanEmploy(typeof(Unrelated))); - } - - - /// - /// Tests whether the instance employer throws an exception when it is asked to - /// employ an abstract class - /// - [Test] - public void TestThrowOnEmployAbstractClass() { - InstanceEmployer testEmployer = new InstanceEmployer(); - - Assert.Throws( - delegate() { testEmployer.Employ(typeof(Base)); } - ); - } - - /// - /// Tests whether the instance employer throws an exception when it is asked to - /// employ a class that is not the product type or a derivative thereof - /// - [Test] - public void TestThrowOnEmployUnrelatedClass() { - InstanceEmployer testEmployer = new InstanceEmployer(); - - Assert.Throws( - delegate() { testEmployer.Employ(typeof(Unrelated)); } - ); - } - - /// - /// Tests whether the instance employer throws an exception when it is asked to - /// employ a class that requires generic parameters for instantiation - /// - [Test] - public void TestThrowOnEmployGenericClass() { - InstanceEmployer testEmployer = new InstanceEmployer(); - - Assert.Throws( - delegate() { testEmployer.Employ(typeof(GenericDerived<>)); } - ); - } - - /// - /// Tests whether the instance employer can employ a class derived from the product - /// - [Test] - public void TestEmployClassDerivedFromProduct() { - InstanceEmployer testEmployer = new InstanceEmployer(); - - testEmployer.Employ(typeof(Derived)); - - Assert.AreEqual(1, testEmployer.Instances.Count); - Assert.AreEqual(typeof(Derived), testEmployer.Instances[0].GetType()); - Assert.IsInstanceOf(testEmployer.Instances[0]); - } - - /// - /// Tests whether the instance employer can employ the product class itself if it - /// isn't abstract - /// - [Test] - public void TestEmployProduct() { - InstanceEmployer testEmployer = new InstanceEmployer(); - - testEmployer.Employ(typeof(Unrelated)); - - Assert.AreEqual(1, testEmployer.Instances.Count); - Assert.AreEqual(typeof(Unrelated), testEmployer.Instances[0].GetType()); - Assert.IsInstanceOf(testEmployer.Instances[0]); - } - - } - -} // namespace Nuclex.Support.Plugins - -#endif // UNITTEST diff --git a/Source/Plugins/InstanceEmployer.cs b/Source/Plugins/InstanceEmployer.cs deleted file mode 100644 index 24a8a19..0000000 --- a/Source/Plugins/InstanceEmployer.cs +++ /dev/null @@ -1,80 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; -using System.Collections.Generic; - -namespace Nuclex.Support.Plugins { - - /// Employer that directly creates instances of the types in a plugin - /// Interface or base class required for the employed types - /// - /// - /// This employer directly creates an instance of any type in a plugin assembly that - /// implements or is derived from the type the generic InstanceEmployer is instanced - /// to. This is useful when the plugin user already has a special plugin interface - /// through which additional informations about a plugin type can be queried or - /// when actually exactly one instance per plugin type is wanted (think of the - /// prototype pattern for example) - /// - /// - /// Because this employer blindly creates an instance of any compatible type found - /// in a plugin assembly it should be used with care. If big types with high - /// construction time or huge memory requirements are loaded this can become - /// a real resource hog. The intention of this employer was to let the plugin user - /// define his own factory interface which possibly provides further details about - /// the type the factory is reponsible for (like a description field). This - /// factory would then be implemented on the plugin side. - /// - /// - public class InstanceEmployer : Employer { - - /// Initializes a new instance employer - public InstanceEmployer() { - this.employedInstances = new List(); - } - - /// All instances that have been employed - public List Instances { - get { return this.employedInstances; } - } - - /// Determines whether the type suites the employer's requirements - /// Type that is checked for employability - /// True if the type can be employed - public override bool CanEmploy(Type type) { - return - type.HasDefaultConstructor() && - typeof(TEmployedType).IsAssignableFrom(type) && - !type.ContainsGenericParameters; - } - - /// Employs the specified plugin type - /// Type to be employed - public override void Employ(Type type) { - this.employedInstances.Add((TEmployedType)Activator.CreateInstance(type)); - } - - /// All instances employed by the instance employer - private List employedInstances; - - } - -} // namespace Nuclex.Support.Plugins diff --git a/Source/Plugins/NoPluginAttribute.Test.cs b/Source/Plugins/NoPluginAttribute.Test.cs deleted file mode 100644 index 0a51fda..0000000 --- a/Source/Plugins/NoPluginAttribute.Test.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; -using System.IO; - -#if UNITTEST - -using NUnit.Framework; - -namespace Nuclex.Support.Plugins { - - /// Unit Test for the no plugin attribute class - [TestFixture] - internal class NoPluginAttributeTest { - - /// - /// Tests whether the default consturctor of the no plugin attribute works - /// - [Test] - public void HasDefaultConstructor() { - Assert.NotNull(new NoPluginAttribute()); - } - - } - -} // namespace Nuclex.Support.Plugins - -#endif // UNITTEST diff --git a/Source/Plugins/NoPluginAttribute.cs b/Source/Plugins/NoPluginAttribute.cs deleted file mode 100644 index cd55132..0000000 --- a/Source/Plugins/NoPluginAttribute.cs +++ /dev/null @@ -1,38 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; - -namespace Nuclex.Support.Plugins { - - /// Attribute that prevents a class from being seen by the PluginHost - /// - /// When this attribute is attached to a class it will be invisible to the - /// PluginHost and not become accessable as a plugin. - /// - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] - public class NoPluginAttribute : Attribute { - - /// Initializes an instance of the NoPluginAttributes - public NoPluginAttribute() : base() { } - - } - -} // namespace Nuclex.Support.Plugins diff --git a/Source/Plugins/PluginHost.Test.cs b/Source/Plugins/PluginHost.Test.cs deleted file mode 100644 index d882a6b..0000000 --- a/Source/Plugins/PluginHost.Test.cs +++ /dev/null @@ -1,168 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; -using System.IO; -using System.Reflection; - -#if UNITTEST - -using NUnit.Framework; - -namespace Nuclex.Support.Plugins { - - /// Unit Test for the plugin host class - [TestFixture, NoPlugin] // NoPlugin is used in one of the unit tests - internal class PluginHostTest { - - #region class FailingEmployer - - /// Employer that unexpectedly fails to employ a given type - private class FailingEmployer : Employer { - - /// Employs the specified plugin type - /// Type to be employed - public override void Employ(Type type) { - if(type.Equals(typeof(PluginRepository))) { - throw new InvalidOperationException(); - } - } - - } - - #endregion // class FailingEmployer - - /// Tests whether the simple constructor is working - [Test] - public void TestSimpleConstructor() { - new PluginHost(new FactoryEmployer()); - } - - /// Tests whether the full constructor is working - [Test] - public void TestFullConstructor() { - new PluginHost(new FactoryEmployer(), new PluginRepository()); - } - - /// - /// Tests whether the AddAssembly() method works by adding the test assembly - /// itself to the repository - /// - [Test] - public void TestFullConstructorWithPreloadedAssembly() { - PluginRepository testRepository = new PluginRepository(); - FactoryEmployer testEmployer = new FactoryEmployer(); - - // Might also use Assembly.GetCallingAssembly() here, but this leads to the exe of - // the unit testing tool - Assembly self = Assembly.GetAssembly(GetType()); - testRepository.AddAssembly(self); - - PluginHost testHost = new PluginHost(testEmployer, testRepository); - - Assert.AreSame(testEmployer, testHost.Employer); - Assert.AreEqual(1, testEmployer.Factories.Count); - } - - /// - /// Verifies that the plugin host correctly stores the provided repository - /// - [Test] - public void TestRepositoryStorage() { - PluginRepository testRepository = new PluginRepository(); - FactoryEmployer testEmployer = new FactoryEmployer(); - PluginHost testHost = new PluginHost(testEmployer, testRepository); - - Assert.AreSame(testRepository, testHost.Repository); - } - - /// - /// Verifies that the plugin host correctly stores the provided employer - /// - [Test] - public void TestEmployerStorage() { - PluginRepository testRepository = new PluginRepository(); - FactoryEmployer testEmployer = new FactoryEmployer(); - PluginHost testHost = new PluginHost(testEmployer, testRepository); - - Assert.AreSame(testEmployer, testHost.Employer); - } - - /// - /// Tests whether the plugin host noticed when new assemblies are loaded into - /// the repository - /// - [Test] - public void TestAssemblyLoading() { - PluginRepository testRepository = new PluginRepository(); - FactoryEmployer testEmployer = new FactoryEmployer(); - - PluginHost testHost = new PluginHost(testEmployer, testRepository); - - // Might also use Assembly.GetCallingAssembly() here, but this leads to the exe of - // the unit testing tool - Assembly self = Assembly.GetAssembly(GetType()); - testRepository.AddAssembly(self); - - Assert.AreSame(testEmployer, testHost.Employer); - Assert.AreEqual(1, testEmployer.Factories.Count); - } - - /// - /// Tests whether the plugin host isolates the caller from an exception when the - /// employer fails to employ a type in the assembly - /// - [Test] - public void TestAssemblyLoadingWithEmployFailure() { - PluginRepository testRepository = new PluginRepository(); - PluginHost testHost = new PluginHost(new FailingEmployer(), testRepository); - - // Might also use Assembly.GetCallingAssembly() here, but this leads to the exe of - // the unit testing tool - Assembly self = Assembly.GetAssembly(GetType()); - testRepository.AddAssembly(self); - - Assert.AreSame(testRepository, testHost.Repository); - } - - /// - /// Verifies that the plugin host ignores types which have the NoPluginAttribute - /// assigned to them - /// - [Test] - public void TestAssemblyLoadingWithNoPluginAttribute() { - PluginRepository testRepository = new PluginRepository(); - FactoryEmployer testEmployer = new FactoryEmployer(); - PluginHost testHost = new PluginHost(testEmployer, testRepository); - - // Might also use Assembly.GetCallingAssembly() here, but this leads to the exe of - // the unit testing tool - Assembly self = Assembly.GetAssembly(GetType()); - testRepository.AddAssembly(self); - - Assert.AreSame(testRepository, testHost.Repository); - Assert.AreEqual(0, testEmployer.Factories.Count); - } - - } - -} // namespace Nuclex.Support.Plugins - -#endif // UNITTEST diff --git a/Source/Plugins/PluginHost.cs b/Source/Plugins/PluginHost.cs deleted file mode 100644 index 0344d07..0000000 --- a/Source/Plugins/PluginHost.cs +++ /dev/null @@ -1,121 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; -using System.Diagnostics; -using System.Reflection; - -namespace Nuclex.Support.Plugins { - - /// Integration host for plugins - /// - /// This class is created by the party that is interested in loading plugins, - /// herein referred to as the "plugin user". The plugin host will monitor a - /// repository and react to any assembly being loaded into that repository by - /// iterating over all types (as in classes and structures) found in the - /// assembly and using the employer to do whatever the plugin user intends - /// to do with the types found in that assembly - /// - public class PluginHost { - - /// Initializes a plugin host using a new repository - /// Employer used assess and employ the plugin types - public PluginHost(Employer employer) : - this(employer, new PluginRepository()) { } - - /// Initializes the plugin using an existing repository - /// Employer used assess and employ the plugin types - /// Repository in which plugins will be stored - public PluginHost(Employer employer, PluginRepository repository) { - this.employer = employer; - this.repository = repository; - - foreach(Assembly assembly in this.repository.LoadedAssemblies) { - employAssemblyTypes(assembly); - } - - this.repository.AssemblyLoaded += new AssemblyLoadEventHandler(assemblyLoadHandler); - } - - /// The repository containing all loaded plugins - public PluginRepository Repository { - get { return this.repository; } - } - - /// The employer that is used by this plugin integration host - public Employer Employer { - get { return this.employer; } - } - - /// Responds to a new plugin being loaded into the repository - /// Repository into which the assembly was loaded - /// Event arguments; contains the loaded assembly - private void assemblyLoadHandler(object sender, AssemblyLoadEventArgs arguments) { - employAssemblyTypes(arguments.LoadedAssembly); - } - - /// Employs all employable types in an assembly - /// Assembly whose types to assess and to employ - private void employAssemblyTypes(Assembly assembly) { - - // Iterate all types contained in the assembly - Type[] types = assembly.GetTypes(); - for(int index = 0; index < types.Length; ++index) { - Type type = types[index]; - - // We'll ignore abstract and non-public types - if(!type.IsPublic || type.IsAbstract) { - continue; - } - - // Types that have been tagged with the [NoPlugin] attribute will be ignored - if(type.HasAttribute()) { - continue; - } - - // Type seems to be acceptable, assess and possibly employ it - try { - if(this.employer.CanEmploy(type)) { - this.employer.Employ(type); - } - } - catch(Exception exception) { - reportError("Could not employ " + type.ToString() + ": " + exception.Message); - } - } - - } - - /// Reports an error to the debugging console - /// Error message that will be reported - private static void reportError(string error) { -#if WINDOWS - Trace.WriteLine(error); -#endif - } - - /// Employs and manages types in the loaded plugin assemblies - private Employer employer; - /// Repository containing all plugins loaded, shared with other hosts - private PluginRepository repository; - - } - -} // namespace Nuclex.Support.Plugins diff --git a/Source/Plugins/PluginRepository.Test.cs b/Source/Plugins/PluginRepository.Test.cs deleted file mode 100644 index 716ef77..0000000 --- a/Source/Plugins/PluginRepository.Test.cs +++ /dev/null @@ -1,222 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; -using System.Diagnostics; -using System.IO; -using System.Reflection; - -#if UNITTEST - -using NUnit.Framework; -using NMock; - -namespace Nuclex.Support.Plugins { - - /// Unit Test for the plugin repository class - [TestFixture] - internal class PluginRepositoryTest { - - #region interface IAssemblyLoadedSubscriber - - /// Interface used to test the progress tracker - public interface IAssemblyLoadedSubscriber { - - /// - /// Represents the method that handles the System.AppDomain.AssemblyLoad event - /// of an System.AppDomain - /// - /// The source of the event. - /// - /// An System.AssemblyLoadEventArgs that contains the event data - /// - void AssemblyLoaded(object sender, AssemblyLoadEventArgs arguments); - - } - - #endregion // interface IProgressTrackerSubscriber - - #region class TestAssemblyLoader - - /// Special assembly loader for the unit test - public class TestAssemblyLoader : PluginRepository.DefaultAssemblyLoader { - - /// Loads an assembly from a file system path - /// Path the assembly will be loaded from - /// The loaded assembly - protected override Assembly LoadAssemblyFromFile(string path) { - switch(path) { - case "DllNotFound": { - Trace.WriteLine("Simulating DllNotFoundException for unit test"); - throw new DllNotFoundException(); - } - case "UnauthorizedAccess": { - Trace.WriteLine("Simulating UnauthorizedAccessException for unit test"); - throw new UnauthorizedAccessException(); - } - case "BadImageFormat": { - Trace.WriteLine("Simulating BadImageFormatException for unit test"); - throw new BadImageFormatException(); - } - case "IO": { - Trace.WriteLine("Simulating IOException for unit test"); - throw new IOException(); - } - default: { return Assembly.LoadFile(path); } - } - } - - } - - #endregion // class TestAssemblyLoader - - /// - /// Tests whether the default constructor of the plugin repository class works - /// - [Test] - public void TestDefaultConstructor() { - new PluginRepository(); - } - - /// - /// Tests whether the AddFiles() method accepts a file mask to which there are - /// no matching files - /// - [Test] - public void TestAddFilesWithZeroMatches() { - PluginRepository testRepository = new PluginRepository(); - testRepository.AddFiles(Guid.NewGuid().ToString()); - } - - /// - /// Tests whether the AddFiles() method accepts a file mask to which there is - /// exactly one matching file - /// - [Test] - public void TestAddFilesWithOwnAssembly() { - PluginRepository testRepository = new PluginRepository(); - - Assembly self = Assembly.GetAssembly(GetType()); - testRepository.AddFiles(self.Location); - - Assert.AreEqual(1, testRepository.LoadedAssemblies.Count); - } - - /// - /// Tests whether the AddAssembly() method works by adding the test assembly - /// itself to the repository - /// - [Test] - public void TestAddAssembly() { - PluginRepository testRepository = new PluginRepository(); - - // Might also use Assembly.GetCallingAssembly() here, but this leads to the exe of - // the unit testing tool - Assembly self = Assembly.GetAssembly(GetType()); - testRepository.AddAssembly(self); - - Assert.AreEqual(1, testRepository.LoadedAssemblies.Count); - } - - /// - /// Tests whether the AddAssembly() method works by adding the test assembly - /// itself to the repository - /// - [Test] - public void TestAssemblyLoadedEvent() { - MockFactory mockery = new MockFactory(); - - PluginRepository testRepository = new PluginRepository(); - Mock subscriber = mockSubscriber(mockery, testRepository); - - subscriber.Expects.One.Method(m => m.AssemblyLoaded(null, null)).WithAnyArguments(); - - Assembly self = Assembly.GetAssembly(GetType()); - testRepository.AddAssembly(self); - - mockery.VerifyAllExpectationsHaveBeenMet(); - } - - /// - /// Verifies that no exceptions come through when a DllNotFoundException is thrown - /// during assembly loading - /// - [Test] - public void TestDllNotFoundExceptionDuringAssemblyLoad() { - TestAssemblyLoader loader = new TestAssemblyLoader(); - Assembly loadedAssembly; - Assert.IsFalse(loader.TryLoadFile("DllNotFound", out loadedAssembly)); - } - - /// - /// Verifies that no exceptions come through when a UnauthorizedAccessException is - /// thrown during assembly loading - /// - [Test] - public void TestUnauthorizedAccessExceptionDuringAssemblyLoad() { - TestAssemblyLoader loader = new TestAssemblyLoader(); - Assembly loadedAssembly; - Assert.IsFalse(loader.TryLoadFile("UnauthorizedAccess", out loadedAssembly)); - } - - /// - /// Verifies that no exceptions come through when a BadImageFormatException is - /// thrown during assembly loading - /// - [Test] - public void TestBadImageFormatExceptionDuringAssemblyLoad() { - TestAssemblyLoader loader = new TestAssemblyLoader(); - Assembly loadedAssembly; - Assert.IsFalse(loader.TryLoadFile("BadImageFormat", out loadedAssembly)); - } - - /// - /// Verifies that no exceptions come through when an IOException is - /// thrown during assembly loading - /// - [Test] - public void TestIOExceptionDuringAssemblyLoad() { - TestAssemblyLoader loader = new TestAssemblyLoader(); - Assembly loadedAssembly; - Assert.IsFalse(loader.TryLoadFile("IO", out loadedAssembly)); - } - - /// Mocks a subscriber for the events of a plugin repository - /// Mockery to create an event subscriber in - /// Repository to subscribe the mocked subscriber to - /// The mocked event subscriber - private static Mock mockSubscriber( - MockFactory mockery, PluginRepository repository - ) { - Mock mockedSubscriber = - mockery.CreateMock(); - - repository.AssemblyLoaded += new AssemblyLoadEventHandler( - mockedSubscriber.MockObject.AssemblyLoaded - ); - - return mockedSubscriber; - } - - } - -} // namespace Nuclex.Support.Plugins - -#endif // UNITTEST diff --git a/Source/Plugins/PluginRepository.cs b/Source/Plugins/PluginRepository.cs deleted file mode 100644 index 40a6dca..0000000 --- a/Source/Plugins/PluginRepository.cs +++ /dev/null @@ -1,193 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Reflection; - -namespace Nuclex.Support.Plugins { - - /// Stores loaded plugins - /// - /// This class manages a set of assemblies that have been dynamically loaded - /// as plugins. It usually is shared by multiple PluginHosts that handle - /// different interfaces of one plugin type. - /// - public class PluginRepository { - - #region class DefaultAssemblyLoader - - /// Default assembly loader used to read assemblies from files - public class DefaultAssemblyLoader : IAssemblyLoader { - - /// Initializes a new default assembly loader - /// - /// Made protected to provide users with a small incentive for using - /// the Instance property instead of creating new instances all around. - /// - protected DefaultAssemblyLoader() { } - - /// Loads an assembly from a file system path - /// Path the assembly will be loaded from - /// The loaded assembly - protected virtual Assembly LoadAssemblyFromFile(string path) { - return Assembly.LoadFrom(path); - } - - /// Tries to loads an assembly from a file - /// Path to the file that is loaded as an assembly - /// - /// Output parameter that receives the loaded assembly or null - /// - /// True if the assembly was loaded successfully, otherwise false - public bool TryLoadFile(string path, out Assembly loadedAssembly) { - - // A lot of errors can occur when attempting to load an assembly... - try { - loadedAssembly = LoadAssemblyFromFile(path); - return true; - } -#if WINDOWS - // File not found - Most likely a missing dependency of the assembly we - // attempted to load since the assembly itself has been found by the GetFiles() method - catch(DllNotFoundException) { - reportError( - "Assembly '" + path + "' or one of its dependencies is missing" - ); - } -#endif - // Unauthorized acccess - Either the assembly is not trusted because it contains - // code that imposes a security risk on the system or a user rights problem - catch(UnauthorizedAccessException) { - reportError( - "Not authorized to load assembly '" + path + "', " + - "possible rights problem" - ); - } - // Bad image format - This exception is often thrown when the assembly we - // attempted to load requires a different version of the .NET framework - catch(BadImageFormatException) { - reportError( - "'" + path + "' is not a .NET assembly, requires a different version " + - "of the .NET Runtime or does not support the current instruction set (x86/x64)" - ); - } - // Unknown error - Our last resort is to show a default error message - catch(Exception exception) { - reportError( - "Failed to load plugin assembly '" + path + "': " + exception.Message - ); - } - - loadedAssembly = null; - return false; - - } - - /// The only instance of the DefaultAssemblyLoader - public static readonly DefaultAssemblyLoader Instance = - new DefaultAssemblyLoader(); - - } - - #endregion // class DefaultAssemblyLoader - - /// Triggered whenever a new assembly is loaded into this repository - public event AssemblyLoadEventHandler AssemblyLoaded; - - /// Initializes a new instance of the plugin repository - public PluginRepository() : this(DefaultAssemblyLoader.Instance) { } - - /// Initializes a new instance of the plugin repository - /// - /// Loader to use for loading assemblies into this repository - /// - public PluginRepository(IAssemblyLoader loader) { - this.assemblies = new List(); - this.assemblyLoader = loader; - } - - /// Loads all plugins matching a wildcard specification - /// Path of one or more plugins via wildcard - /// - /// This function always assumes that a plugin is optional. This means that - /// even when you specify a unique file name and a matching file is not found, - /// no exception will be raised and the error is silently ignored. - /// - public void AddFiles(string wildcard) { - string directory = Path.GetDirectoryName(wildcard); - string search = Path.GetFileName(wildcard); - - // If no directory was specified, use the current working directory - if((directory == null) || (directory == string.Empty)) { - directory = "."; - } - - // We'll scan the specified directory for all files matching the specified - // wildcard. If only a single file is specified, only that file will match - // the supposed wildcard and everything works as expected - string[] assemblyFiles = Directory.GetFiles(directory, search); - foreach(string assemblyFile in assemblyFiles) { - - Assembly loadedAssembly; - if(this.assemblyLoader.TryLoadFile(assemblyFile, out loadedAssembly)) { - AddAssembly(loadedAssembly); - } - - } - } - - /// Adds the specified assembly to the repository - /// - /// Also used internally, so any assembly that is to be put into the repository, - /// not matter how, wanders through this method - /// - public void AddAssembly(Assembly assembly) { - this.assemblies.Add(assembly); - - // Trigger event in case any subscribers have been registered - if(AssemblyLoaded != null) { - AssemblyLoaded(this, new AssemblyLoadEventArgs(assembly)); - } - } - - /// List of all loaded plugin assemblies in the repository - public List LoadedAssemblies { - get { return this.assemblies; } - } - - /// Reports an error to the debugging console - /// Error message that will be reported - private static void reportError(string error) { -#if WINDOWS - Trace.WriteLine(error); -#endif - } - - /// Loaded plugin assemblies - private List assemblies; - /// Takes care of loading assemblies for the repositories - private IAssemblyLoader assemblyLoader; - - } - -} // namespace Nuclex.Support.Plugins diff --git a/Source/Plugins/PrototypeFactory.Test.cs b/Source/Plugins/PrototypeFactory.Test.cs deleted file mode 100644 index b73636d..0000000 --- a/Source/Plugins/PrototypeFactory.Test.cs +++ /dev/null @@ -1,141 +0,0 @@ -#region CPL License -/* -Nuclex Framework -Copyright (C) 2002-2012 Nuclex Development Labs - -This library is free software; you can redistribute it and/or -modify it under the terms of the IBM Common Public License as -published by the IBM Corporation; either version 1.0 of the -License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -IBM Common Public License for more details. - -You should have received a copy of the IBM Common Public -License along with this library -*/ -#endregion - -#if UNITTEST - -using System; -using System.IO; - -using NUnit.Framework; - -namespace Nuclex.Support.Plugins { - - /// Unit Test for the prototype-based factory class - [TestFixture] - internal class PrototypeFactoryTest { - - #region interface IProduct - - /// Interface used for the product in the unit test - private interface IProduct { - /// Some value associated with the product - int Value { get; } - } - - #endregion // interface IProduct - - #region class ConcretePrototype - - /// - /// Class derived from the abstract base to serve as concrete product for - /// testing the factory employer - /// - private class ConcretePrototype : IProduct, ICloneable, IDisposable { - - /// Initializes a new instance of the prototype product - /// Value that will be associated with this instance - public ConcretePrototype(int value) { - this.value = value; - } - - /// Immediately releases all resources owned by the instance - public void Dispose() { - this.disposed = true; - } - - /// Value the product has been associated with - public int Value { get { return this.value; } } - - /// Whether the prototype instance has been disposed - public bool IsDisposed { - get { return this.disposed; } - } - - /// Creates an identical copy of the instance - /// An identical copy of the instance - object ICloneable.Clone() { - return new ConcretePrototype(this.value); - } - - /// Value associated with the product - private int value; - /// Whether the instance has been disposed - private bool disposed; - - } - - #endregion // class ConcretePrototype - - /// - /// Tests whether the prototype-based factory behaves correctly by creating - /// new instances of its product using clones of its assigned prototype. - /// - [Test] - public void TestGenericInstanceCreation() { - ConcretePrototype template = new ConcretePrototype(42); - - IAbstractFactory factory = new PrototypeFactory< - IProduct, ConcretePrototype - >(template); - - IProduct factoryCreatedProduct = factory.CreateInstance(); - - Assert.AreEqual(template.Value, factoryCreatedProduct.Value); - } - - /// - /// Tests whether the prototype-based factory behaves correctly by creating - /// new instances of its product using clones of its assigned prototype. - /// - [Test] - public void TestInstanceCreation() { - ConcretePrototype template = new ConcretePrototype(42); - - IAbstractFactory factory = new PrototypeFactory< - IProduct, ConcretePrototype - >(template); - - IProduct factoryCreatedProduct = (IProduct)factory.CreateInstance(); - - Assert.AreEqual(template.Value, factoryCreatedProduct.Value); - } - - /// - /// Tests whether the prototype is disposed if it implements the IDisposable - /// interface and the factory is explicitely disposed. - /// - [Test] - public void TestPrototypeDisposal() { - ConcretePrototype template = new ConcretePrototype(42); - - PrototypeFactory factory = new PrototypeFactory< - IProduct, ConcretePrototype - >(template); - - Assert.IsFalse(template.IsDisposed); - factory.Dispose(); - Assert.IsTrue(template.IsDisposed); - } - - } - -} // namespace Nuclex.Support.Plugins - -#endif // UNITTEST diff --git a/Source/Plugins/PrototypeFactory.cs b/Source/Plugins/PrototypeFactory.cs deleted file mode 100644 index 49b22ee..0000000 --- a/Source/Plugins/PrototypeFactory.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Nuclex.Support.Plugins { - -#if !NO_CLONING - - /// Factory that creates instances by cloning a prototype - /// Type of product created by the factory - /// Type of the prototype that will be cloned - public class PrototypeFactory : - IAbstractFactory, IAbstractFactory, IDisposable - where TProduct : class - where TConcreteType : class, ICloneable { - - /// Initializes a new prototype based factory - /// Prototype instance that will be cloned - public PrototypeFactory(TConcreteType prototype) { - this.prototype = prototype; - } - - /// - /// Creates a new instance of the type to which the factory is specialized - /// - /// The newly created instance - public TProduct CreateInstance() { - return (TProduct)this.prototype.Clone(); - } - - /// - /// Creates a new instance of the type to which the factory is specialized - /// - /// The newly created instance - object IAbstractFactory.CreateInstance() { - return this.prototype.Clone(); - } - - /// Immediately releases all resources owned by the instance - public void Dispose() { - if(this.prototype != null) { - IDisposable disposablePrototype = this.prototype as IDisposable; - if(disposablePrototype != null) { - disposablePrototype.Dispose(); - } - - this.prototype = null; - } - } - - /// The prototype object - private TConcreteType prototype; - - } - -#endif // !NO_CLONING - -} // namespace Nuclex.Support.Plugins