I'm trying to write a method that finds all types in an assembly with a specific custom attribute. I also need to be able to supply a string value to match on. The caveat is that I would like to be able to run this on any class and return any value.
For example: I would like to execute a call like this
Type tTest = TypeFinder.GetTypesWithAttributeValue(Assembly.Load("MyAssembly"), typeof(DiagnosticTestAttribute), "TestName", "EmailTest");
My method so far looks like this:
public static Type GetTypesWithAttributeValue(Assembly aAssembly, Type tAttribute, string sPropertyName, object oValue)
{
object oReturn = null;
foreach (Type type in aAssembly.GetTypes())
{
foreach (object oTemp in type.GetCustomAttributes(tAttribute, true))
{
//if the attribute we are looking for matches
//the value we are looking for, return the current type.
}
}
return typeof(string); //otherwise return a string type
}
My Attribute looks like this:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class DiagnosticTestAttribute : Attribute
{
private string _sTestName = string.Empty;
public string TestName
{
get { return _sTestName; }
}
public DiagnosticTest(string sTestName)
{
_sTestName = sTestName;
}
}
For those familiar with expressions, I would really like to be able to make a call like:
TypeFinder.GetTypesWithAttributeValue<DiagnosticTestAttribute>(Assembly.Load("MyAssembly"), x=> x.TestName, "EmailTest");
Where the expression uses my generic type to select the property that I'm looking for.
This should work:
public static Type GetTypeWithAttributeValue<TAttribute>(Assembly aAssembly, Func<TAttribute, object> pred, object oValue) {
foreach (Type type in aAssembly.GetTypes()) {
foreach (TAttribute oTemp in type.GetCustomAttributes(typeof(TAttribute), true)) {
if (Equals(pred(oTemp), oValue)) {
return type;
}
}
}
return typeof(string); //otherwise return a string type
}
Or even nicer:
public static Type GetTypeWithAttributeValue<TAttribute>(Assembly aAssembly, Predicate<TAttribute> pred) {
foreach (Type type in aAssembly.GetTypes()) {
foreach (TAttribute oTemp in type.GetCustomAttributes(typeof(TAttribute), true)) {
if (pred(oTemp)) {
return type;
}
}
}
return typeof(string); //otherwise return a string type
}
This is how the invocation looks like:
GetTypeWithAttributeValue<DefaultValueAttribute>(Assembly.GetCallingAssembly(), attribute => attribute.Value,
"string");
and this one respectively:
GetTypeWithAttributeValue<DefaultValueAttribute>(Assembly.GetCallingAssembly(),
attribute => attribute.Value == "string");