如何编写访问器表达式来推断类型?

时间:2016-07-23 19:25:41

标签: c# .net lambda extension-methods

给出以下代码

[Table("Bar")]
public class Foo {
  [Column("BarID")]
  public int Id { get; set; }
}
public static class MyExtensions {
  public static string TableName(this Type type) {
    var attrib = type.GetCustomAttribute<TableAttribute>(false);
    return attrib?.Name ?? type.Name;
  }
  public static string ColumnName<TType, TMember>(this Type t, Expression<Func<TType, TMember>> accessor) {
    var member = accessor.Body as MemberExpression;
    if (member != null) {
      var field = member.Member;
      var attrib = field.GetCustomAttribute<ColumnAttribute>();
      return attrib?.Name ?? field.Name;
    }
    return null;
  }
}

然后我可以编写像typeof(Foo).TableName();这样的代码来获取表名

对于列名,我可以使用typeof(Foo).ColumnName((Foo f) => f.Id)

如何获取ColumnName扩展方法以在存取器表达式中推断TType,以便我可以简单地编码为type(Foo).ColumnName(f => f.Id)

2 个答案:

答案 0 :(得分:0)

由于您甚至不在方法中使用参数Type t,为什么它甚至必须是扩展方法?

public static string ColumnName<TType, TMember>(
    Expression<Func<TType, TMember>> accessor) { ... }

用法:

ColumnName((Foo f) => f.Id)

这种类型只指定一次。

答案 1 :(得分:0)

我最终得到了以下

public static class Metadata<TType> {
  public static string TableName() {
    var type = typeof(TType);
    var attrib = type.GetCustomAttribute<TableAttribute>(false);
    return attrib?.Name ?? type.Name;
  }
  public static string ColumnName<TMember>(Expression<Func<TType, TMember>> propertyExpresseion) {
    if (propertyExpresseion.Body.NodeType != ExpressionType.MemberAccess) {
      throw new InvalidOperationException();
    }

    var member = propertyExpresseion.Body as MemberExpression;
    var property = member.Member;
    var attrib = property.GetCustomAttribute<ColumnAttribute>(false);
    return attrib?.Name ?? property.Name;
  }
}

然后我可以用作

Metadata<Audit>.TableName();
Metadata<Audit>.ColumnName(a => a.Id);