2016-07-23 60 views
1

考慮下面的代碼如何編寫存取器表達式來推斷類型?

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

+1

你的第二個方法不使用't' ...這不是真的在所有類型擴展(它的意義在於它實際上會從一個類型對象中被調用,但是你不會使用它的值)。泛型類型參數不能直接從類型對象中替換。你會得到一些通用的唯一方法是採用該類型並使用反射創建一個通用方法定義,但在這種情況下,你會被卡住返回對象(我認爲)..你可以隨時讓你的擴展方法擴展你的實體類型直接('MyEntity t'),並將方法限制在那裏'MyEntity:EntityBase' – pinkfloydx33

+0

@ pinkfloydx33是的,我意識到這一點。我只想擁有相同的API來獲取屬性上的ColumnAttribute值。如果訪問器方法不起作用,那麼我可以創建一個可以稱爲'typeof(Foo).ColumnName(nameof(Foo.Id))'的方法' – user2321864

+0

您仍可以使用表達式API來獲取成員表達式,而不是nameof,問題是從類型對象創建泛型類型參數,而不直接指定genric類型。既然你已經知道Foo,爲什麼不把它作爲方法調用的一部分來提供呢? 'ColumnName (f => f.Id)'並且拋出具有一個參數的普通靜態方法的擴展方面? – pinkfloydx33

回答

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

由於您甚至不使用參數012該方法中的,爲什麼它甚至必須是擴展方法?

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

用法:

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

這樣的類型被指定一次。