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

How to write accessor expression to infer the type?

给定以下代码

[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(); 的代码来获取 table 名称

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

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

既然连方法中的参数Type t都不用,为什么还要是扩展方法呢?

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

用法:

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

这种方式只指定一次类型。

我得到了以下结果

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);