Pluggable Frameworks and Libraries - Discovering Classes Using Reflection and Attributes

Pluggable Frameworks and Libraries - Discovering Classes Using Reflection and Attributes

by David Hayden ( Microsoft MVP C# ), Filed: C#

 

Based on ExpressionEvaluators that I mentioned in the following post to help evaluate expressions in the configuration of my dependency injection tool:

One could make ExpressionEvaluators ( and any classes ) more pluggable and discoverable by putting all the ExpressionEvaluators in a single assembly ( MyExpressionEvaluators ) for simplicity and decorate them with a custom attribute. Note I am just using fake filler classes to make a point, but here are examples of ExpressionEvaluators that are annotated with an attribute and share a common interface:

 

[ExpressionEvaluator("AppSetting")]
public class AppSettingExpressionEvaluator
                        : IExpressionEvaluator
{
    public string Evaluate(string expression)
    {
        return string.Empty;
    }
}


[ExpressionEvaluator("ConnectionString")]
public class ConnectionStringExpressionEvaluator
                        : IExpressionEvaluator
{
    public string Evaluate(string expression)
    {
        return string.Empty;
    }
}

 

We can then discover and load these into a container using reflection over the assembly:

 

_evaluators = new Dictionary<string,IExpressionEvaluator>();

Assembly assembly = Assembly.Load("MyExpressionEvaluators");

foreach (Type type in assembly.GetTypes())
{
    // Get Custom Attributes if any
    ExpressionEvaluatorAttribute[] attributes =
      (ExpressionEvaluatorAttribute[])type.
      GetCustomAttributes(typeof(ExpressionEvaluatorAttribute),
        false);
        
    // Is this an ExpressionEvaluator
    if (attributes.Length > 0 &&
        typeof(IExpressionEvaluator).IsAssignableFrom(type))
    {
      _evaluators.Add(
        attributes[0].Prefix,
        Activator.CreateInstance(type) as IExpressionEvaluator);
    }
}

 

Now we can use the evaluators to evaluate the input from the configuration:

 

// Pretend this is the expression coming through
// minus tokens $,{,and}
string input = "ConnectionString:MyConnectionString";

// Split into parts
string[] expressionArray = input.Split(':');
string prefix = expressionArray[0];
string expression = expressionArray[1];

// Get the evaluator
IExpressionEvaluator evaluator = _evaluators[prefix];

// Get the results
string results = evaluator.Evaluate(expression);

 

The use of reflections and attributes is one of a number of ways to make an application more pluggable.

 

Feed: David Hayden ( Microsoft MVP C# ), Filed: C#

 

posted on Thursday, October 04, 2007 10:20 PM

Main

News

Green Tea

.NET Development

Enterprise Library

Patterns & Practices