Pool can now be used with types not derived from IRecyclable and/or without a public default constructor; consolidated type-related helper methods into a common helper class (TypeHelper.cs); optimized GetFieldInfosIncludingBaseClasses() method

git-svn-id: file:///srv/devel/repo-conversion/nusu@268 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
Markus Ewald 2012-03-08 11:05:20 +00:00
parent 24439da822
commit c91a082e84
18 changed files with 277 additions and 292 deletions

View file

@ -36,7 +36,7 @@ namespace Nuclex.Support.Plugins {
/// <param name="type">Type which will be assessed</param>
/// <returns>True if the type can be employed, otherwise false</returns>
public virtual bool CanEmploy(Type type) {
return PluginHelper.HasDefaultConstructor(type);
return type.HasDefaultConstructor();
}
/// <summary>Employs the specified plugin type</summary>

View file

@ -24,7 +24,7 @@ using System.Collections.Generic;
namespace Nuclex.Support.Plugins {
/// <summary>Employer to create factories of suiting types found in plugins</summary>
/// <typeparam name="ProductType">
/// <typeparam name="TProduct">
/// Interface or base class that the types need to implement
/// </typeparam>
/// <remarks>
@ -41,12 +41,12 @@ namespace Nuclex.Support.Plugins {
/// a human-readable name, capabilities or an icon.
/// </para>
/// </remarks>
public class FactoryEmployer<ProductType> : Employer where ProductType : class {
public class FactoryEmployer<TProduct> : Employer where TProduct : class {
#region class ConcreteFactory
/// <summary>Concrete factory for the types in a plugin assembly</summary>
private class ConcreteFactory : IAbstractFactory<ProductType>, IAbstractFactory {
private class ConcreteFactory : IAbstractFactory<TProduct>, IAbstractFactory {
/// <summary>
/// Initializes a factory and configures it for the specified product
@ -58,8 +58,8 @@ namespace Nuclex.Support.Plugins {
/// <summary>Create a new instance of the type the factory is configured to</summary>
/// <returns>The newly created instance</returns>
public ProductType CreateInstance() {
return (ProductType)Activator.CreateInstance(this.concreteType);
public TProduct CreateInstance() {
return (TProduct)Activator.CreateInstance(this.concreteType);
}
/// <summary>Create a new instance of the type the factory is configured to</summary>
@ -77,11 +77,11 @@ namespace Nuclex.Support.Plugins {
/// <summary>Initializes a new FactoryEmployer</summary>
public FactoryEmployer() {
this.employedFactories = new List<IAbstractFactory<ProductType>>();
this.employedFactories = new List<IAbstractFactory<TProduct>>();
}
/// <summary>List of all factories that the instance employer has created</summary>
public List<IAbstractFactory<ProductType>> Factories {
public List<IAbstractFactory<TProduct>> Factories {
get { return this.employedFactories; }
}
@ -90,20 +90,20 @@ namespace Nuclex.Support.Plugins {
/// <returns>True if the type can be employed</returns>
public override bool CanEmploy(Type type) {
return
PluginHelper.HasDefaultConstructor(type) &&
typeof(ProductType).IsAssignableFrom(type) &&
type.HasDefaultConstructor() &&
typeof(TProduct).IsAssignableFrom(type) &&
!type.ContainsGenericParameters;
}
/// <summary>Employs the specified plugin type</summary>
/// <param name="type">Type to be employed</param>
public override void Employ(Type type) {
if(!PluginHelper.HasDefaultConstructor(type)) {
if(!type.HasDefaultConstructor()) {
throw new MissingMethodException(
"Cannot employ type because it does not have a public default constructor"
);
}
if(!typeof(ProductType).IsAssignableFrom(type)) {
if(!typeof(TProduct).IsAssignableFrom(type)) {
throw new InvalidCastException(
"Cannot employ type because it cannot be cast to the factory's product type"
);
@ -118,7 +118,7 @@ namespace Nuclex.Support.Plugins {
}
/// <summary>All factories that the instance employer has created</summary>
private List<IAbstractFactory<ProductType>> employedFactories;
private List<IAbstractFactory<TProduct>> employedFactories;
}

View file

@ -24,7 +24,7 @@ using System.Collections.Generic;
namespace Nuclex.Support.Plugins {
/// <summary>Employer that directly creates instances of the types in a plugin</summary>
/// <typeparam name="T">Interface or base class required for the employed types</typeparam>
/// <typeparam name="TEmployedType">Interface or base class required for the employed types</typeparam>
/// <remarks>
/// <para>
/// This employer directly creates an instance of any type in a plugin assembly that
@ -44,15 +44,15 @@ namespace Nuclex.Support.Plugins {
/// factory would then be implemented on the plugin side.
/// </para>
/// </remarks>
public class InstanceEmployer<T> : Employer {
public class InstanceEmployer<TEmployedType> : Employer {
/// <summary>Initializes a new instance employer</summary>
public InstanceEmployer() {
this.employedInstances = new List<T>();
this.employedInstances = new List<TEmployedType>();
}
/// <summary>All instances that have been employed</summary>
public List<T> Instances {
public List<TEmployedType> Instances {
get { return this.employedInstances; }
}
@ -61,19 +61,19 @@ namespace Nuclex.Support.Plugins {
/// <returns>True if the type can be employed</returns>
public override bool CanEmploy(Type type) {
return
PluginHelper.HasDefaultConstructor(type) &&
typeof(T).IsAssignableFrom(type) &&
type.HasDefaultConstructor() &&
typeof(TEmployedType).IsAssignableFrom(type) &&
!type.ContainsGenericParameters;
}
/// <summary>Employs the specified plugin type</summary>
/// <param name="type">Type to be employed</param>
public override void Employ(Type type) {
this.employedInstances.Add((T)Activator.CreateInstance(type));
this.employedInstances.Add((TEmployedType)Activator.CreateInstance(type));
}
/// <summary>All instances employed by the instance employer</summary>
private List<T> employedInstances;
private List<TEmployedType> employedInstances;
}

View file

@ -1,83 +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 {
/// <summary>Unit Test for the plugin helper class</summary>
[TestFixture]
internal class PluginHelperTest {
#region class NoDefaultConstructor
/// <summary>Test class that doesn't have a default constructor</summary>
private class NoDefaultConstructor {
/// <summary>Initializes a new instance of the test class</summary>
/// <param name="dummy">Dummy argument so this is no default constructor</param>
public NoDefaultConstructor(int dummy) { }
}
#endregion // class NoDefaultConstructor
#region class NonPublicDefaultConstructor
/// <summary>Test class that has a non-public default constructor</summary>
private class NonPublicDefaultConstructor {
/// <summary>Initializes a new instance of the test class</summary>
protected NonPublicDefaultConstructor() { }
}
#endregion // class NonPublicDefaultConstructor
#region class PublicDefaultConstructor
/// <summary>Test class that has a public default constructor</summary>
private class PublicDefaultConstructor {
/// <summary>Initializes a new instance of the test class</summary>
public PublicDefaultConstructor() { }
}
#endregion // class PublicDefaultConstructor
/// <summary>Tests whether the default constructor detection works as expected</summary>
[Test]
public void TestDefaultConstructorDetection() {
Assert.IsFalse(
PluginHelper.HasDefaultConstructor(typeof(NoDefaultConstructor))
);
Assert.IsFalse(
PluginHelper.HasDefaultConstructor(typeof(NonPublicDefaultConstructor))
);
Assert.IsTrue(
PluginHelper.HasDefaultConstructor(typeof(PublicDefaultConstructor))
);
}
}
} // namespace Nuclex.Support.Plugins
#endif // UNITTEST

View file

@ -1,44 +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.Reflection;
namespace Nuclex.Support.Plugins {
/// <summary>Supporting functions for the plugin classes</summary>
public static class PluginHelper {
/// <summary>Determines whether the given type has a default constructor</summary>
/// <param name="type">Type which is to be checked</param>
/// <returns>True if the type has a default constructor</returns>
public static bool HasDefaultConstructor(Type type) {
ConstructorInfo[] constructors = type.GetConstructors();
foreach(ConstructorInfo constructor in constructors)
if(constructor.IsPublic && (constructor.GetParameters().Length == 0))
return true;
return false;
}
}
} // namespace Nuclex.Support.Plugins

View file

@ -7,16 +7,16 @@ namespace Nuclex.Support.Plugins {
#if !NO_CLONING
/// <summary>Factory that creates instances by cloning a prototype</summary>
/// <typeparam name="ProductType">Type of product created by the factory</typeparam>
/// <typeparam name="ConcreteType">Type of the prototype that will be cloned</typeparam>
public class PrototypeFactory<ProductType, ConcreteType> :
IAbstractFactory<ProductType>, IAbstractFactory, IDisposable
where ProductType : class
where ConcreteType : class, ICloneable {
/// <typeparam name="TProduct">Type of product created by the factory</typeparam>
/// <typeparam name="TConcreteType">Type of the prototype that will be cloned</typeparam>
public class PrototypeFactory<TProduct, TConcreteType> :
IAbstractFactory<TProduct>, IAbstractFactory, IDisposable
where TProduct : class
where TConcreteType : class, ICloneable {
/// <summary>Initializes a new prototype based factory</summary>
/// <param name="prototype">Prototype instance that will be cloned</param>
public PrototypeFactory(ConcreteType prototype) {
public PrototypeFactory(TConcreteType prototype) {
this.prototype = prototype;
}
@ -24,8 +24,8 @@ namespace Nuclex.Support.Plugins {
/// Creates a new instance of the type to which the factory is specialized
/// </summary>
/// <returns>The newly created instance</returns>
public ProductType CreateInstance() {
return (ProductType)this.prototype.Clone();
public TProduct CreateInstance() {
return (TProduct)this.prototype.Clone();
}
/// <summary>
@ -49,7 +49,7 @@ namespace Nuclex.Support.Plugins {
}
/// <summary>The prototype object</summary>
private ConcreteType prototype;
private TConcreteType prototype;
}