【发布时间】:2016-07-23 19:25:40
【问题描述】:
给定以下代码
[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)
【问题讨论】:
-
您的第二种方法不使用
t... 它根本不是真正扩展 Type (从某种意义上说,它实际上会从类型对象中调用,但您没有t 使用它的值)。不能直接从类型对象替换泛型类型参数。获得泛型的唯一方法是获取类型并使用反射创建泛型方法定义,但在这种情况下,你会被困在返回对象(我认为)。你总是可以让你的扩展方法扩展你的实体类型直接(this MyEntity t)并将方法限制为where MyEntity : EntityBase -
@pinkfloydx33 是的,我意识到了这一点。我只是想拥有相同的 api 来获取属性上的 ColumnAttribute 值。如果访问器方法不起作用,那么我可以创建一个可以调用的方法,例如 'typeof(Foo).ColumnName(nameof(Foo.Id))'
-
您仍然可以使用表达式 API 来获取成员表达式而不是 nameof,问题是从类型对象创建泛型类型参数而不直接指定泛型类型。既然您已经知道 Foo,为什么不将它作为方法调用的一部分提供呢?
ColumnName<Foo, string>(f => f.Id)并放弃扩展方面,转而使用一个参数的普通静态方法? -
虽然我猜在那种情况下你不会知道字符串......你可以将这两种方法与一个辅助扩展结合起来,它使用反射创建一个通用方法,然后调用原始版本。但恐怕你将不得不在 somewhere 指定你的类型......虽然可能有一些解决方案我完全忽略了(毕竟它 is 早上 5 点)
标签: c# .net lambda extension-methods