K
Konstantin Denerz
Hallo,
Auf der Suche nach der Möglichkeit in Spring.Net Expressions (Spring.Expressions) neue Funktionen für Collections zu definieren und zur Laufzeit auf diese zuzugreifen, musste ich feststellen, dass es ohne einen Hack nicht geht.
Hier ist eine Lösung für die dynamische Registrierung von Collection Processors. Zwar ähnelt diese mehr einem Hack als einer sauberen Lösung ist aber anders ohne größere Änderungen am Spring.Net Framework selbst nicht durchzuführen.
Die Idee eine Spring Expression für die Registrierung zu verwenden anstatt direkt über Reflection auf das Map mit den Collection Processors zuzugreifen kam von Thomas Darimont. Ich finde die Idee mittlerweile gut, da in diesem Fall die hierdurch entstehende Flexibilität von Vorteil ist.
Program.cs:
DelegateBasedCollectionProcessor.cs:
CollectionProcessorRegistry.cs:
Der Code wurde mit .Net 2.0 / SPRING.net 1.1 getestet.
Gruß Konstantin
Auf der Suche nach der Möglichkeit in Spring.Net Expressions (Spring.Expressions) neue Funktionen für Collections zu definieren und zur Laufzeit auf diese zuzugreifen, musste ich feststellen, dass es ohne einen Hack nicht geht.
Hier ist eine Lösung für die dynamische Registrierung von Collection Processors. Zwar ähnelt diese mehr einem Hack als einer sauberen Lösung ist aber anders ohne größere Änderungen am Spring.Net Framework selbst nicht durchzuführen.
Die Idee eine Spring Expression für die Registrierung zu verwenden anstatt direkt über Reflection auf das Map mit den Collection Processors zuzugreifen kam von Thomas Darimont. Ich finde die Idee mittlerweile gut, da in diesem Fall die hierdurch entstehende Flexibilität von Vorteil ist.
Program.cs:
C#:
public static void Main(string[] args)
{
CollectionProcessorRegistry registry = new CollectionProcessorRegistry();
registry.RegisterExpression = "T(Spring.Expressions.MethodNode)." +
"collectionProcessorMap[#theProcessor.Name]=#theProcessor";
ProcessDelegate processDelegate = delegate(ICollection theSource,
object[] theArguments){
object result = null;
if(theSource != null)
{
ArrayList source = new ArrayList();
source.AddRange(theSource);
foreach(object argument in theArguments)
{
source.Remove(argument);
}
result = source;
}
return result;
};
ICollectionProcessor processor =
new DelegateBasedCollectionProcessor("filter",processDelegate);
registry.Register(processor);
string expression = "{'c',2,1,'x','#'}.filter('x',2,1)";
ICollection resultCollection =
(ICollection)ExpressionEvaluator.GetValue(null,expression);
foreach(object resultElement in resultCollection)
{
Console.Write(resultElement);
}
Console.WriteLine();
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
C#:
using System;
using System.Collections;
using Spring.Expressions.Processors;
namespace Spring.Expressions.Processors
{
/// <summary>
/// Delegate used to delegate to process method.
/// </summary>
public delegate object ProcessDelegate(ICollection theSource, object[] theArguments);
/// <summary>
/// Serves as processor of collections.
/// </summary>
/// <author>konstantin.denerz</author>
public class DelegateBasedCollectionProcessor: ICollectionProcessor
{
#region Constructors
/// <summary>
/// The default constructor.
/// </summary>
/// <param name="theName">The name of the collection processor.</param>
/// <param name="theProcessDelegate">The delegate used to delegate to the process method.</param>
public DelegateBasedCollectionProcessor(string theName, ProcessDelegate theProcessDelegate)
{
this.name = theName;
this.processDelegate = theProcessDelegate;
}
#endregion
#region Properties
/// <summary>
/// Holds the name of the collection processor.
/// </summary>
public string Name
{
get { return name; }
set { name = value; }
} private string name;
private ProcessDelegate processDelegate;
#endregion
#region API
/// <summary>
/// Process the collection.
/// </summary>
/// <param name="theSource">The source collection.</param>
/// <param name="theArguments">The arguments.</param>
/// <returns>Return the result of the process.</returns>
public object Process(ICollection theSource, object[] theArguments)
{
return processDelegate(theSource,theArguments);
}
/// <summary>
/// Return the name of the collection processor.
/// </summary>
/// <returns>The name of the collection processor.</returns>
public override string ToString()
{
return name;
}
#endregion
}
}
C#:
using System;
using System.Collections;
using Spring.Expressions;
using Spring.Expressions.Processors;
namespace Spring.Expressions.Processors
{
/// <summary>
/// Serves as registry service for collection processors.
/// </summary>
/// <author>konstantin.denerz</author>
public class CollectionProcessorRegistry
{
#region Properties
/// <summary>
/// Holds the expression string used to register a collection processor.
/// </summary>
public string RegisterExpression
{
get { return registerExpression; }
set { registerExpression = value; }
} private string registerExpression;
#endregion
#region API
/// <summary>
/// Register a collection processor so that can be used in spring expressions.
/// </summary>
/// <param name="theProcessor">The processor that should be registered.</param>
public void Register(ICollectionProcessor theProcessor)
{
IDictionary variables = new Hashtable();
variables["theProcessor"] = theProcessor;
ExpressionEvaluator.GetValue(null,RegisterExpression,variables);
}
#endregion
}
}
Der Code wurde mit .Net 2.0 / SPRING.net 1.1 getestet.
Gruß Konstantin