从类型动态获取类属性值

11

我正在尝试编写一个方法,用于在程序集中查找具有特定自定义属性的所有类型。我还需要能够提供要匹配的字符串值。但是,我希望能够在任何类上运行此方法并返回任何值。

例如: 我想执行这样的调用

Type tTest = TypeFinder.GetTypesWithAttributeValue(Assembly.Load("MyAssembly"), typeof(DiagnosticTestAttribute), "TestName", "EmailTest");

到目前为止,我的方法看起来是这样的:

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
}

我的属性看起来像这样:

[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;
    }
}

对于熟悉表达式的人,我真的很希望能够像这样调用:

TypeFinder.GetTypesWithAttributeValue<DiagnosticTestAttribute>(Assembly.Load("MyAssembly"), x=> x.TestName, "EmailTest");

表达式使用了我的泛型类型来选择我要查找的属性。

2个回答

14

这应该可以正常工作:

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
}

或者更好的是:

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
}

这是调用的样子:

  GetTypeWithAttributeValue<DefaultValueAttribute>(Assembly.GetCallingAssembly(), attribute => attribute.Value,
                                                    "string");

以及这个分别是:

  GetTypeWithAttributeValue<DefaultValueAttribute>(Assembly.GetCallingAssembly(),
                                                    attribute => attribute.Value == "string");

这个完美无缺地运行了。我不得不更改程序集,因为我是从另一个程序集中调用它的,但它非常好用。非常感谢。 - Andrew Munro
如果我能给你更多的信任度,我一定会的;-) - Seabizkit

2
很久以前,我开发了一些辅助方法来从表达式中提取属性名称。我认为这对你很有用。
public static string Item<TItem, TMember>(this TItem obj, Expression<Func<TItem, TMember>> expression)
{
    if (expression.Body is MemberExpression)
    {
        return ((MemberExpression)(expression.Body)).Member.Name;
    }
    if (expression.Body is UnaryExpression)
    {
        return ((MemberExpression)((UnaryExpression)(expression.Body)).Operand).Member.Name;
    }
    if (expression.Body is ParameterExpression)
    {
        return expression.Body.Type.Name;
    }
    throw new InvalidOperationException();
}

请查看此文件以获取更多信息。


那很有帮助。一旦我能够弄清如何从实例类的属性中提取值,那将有助于我为我的方法创建一个漂亮的界面。谢谢! - Andrew Munro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接