1
這是我的方法。請注意,我對泛型參數R
返回相當於可空類型:我可以創建一個採用值類型或引用類型的泛型方法,但始終返回可爲空的類型
public static Nullable<R> GetValue<T, R>(this T a, Expression<Func<T, R>> expression)
where T : Attribute
where R : struct
{
if (a == null)
return null;
PropertyInfo p = GetProperty(expression);
if (p == null)
return null;
return (R)p.GetValue(a, null);
}
我可以用它在呼叫得到一個屬性的這樣的值:
//I don't throw exceptions for invalid or missing calls
//because I want to chain the calls together:
int maximumLength4 = instance.GetProperty(x => x.ToString())
.GetAttribute<StringLengthAttribute>()
.GetValue(x => x.MaximumLength)
.GetValueOrDefault(50);
我想使用相同的通用方法處理字符串:
//I'd like to use the GetValue generic method with strings as well as integers
string erroMessage = instance.GetProperty(x => x.ToString())
.GetAttribute<StringLengthAttribute>()
.GetValue(x => x.ErrorMessage);
,但它不會編譯:
類型「R」必須是一個非空值類型,以便在通用類型或方法「System.Nullable」
無法隱式轉換類型用它作爲 參數「T」'字符串?以「字符串」
有什麼訣竅,我可以使用這裏得到相同的方法簽名,但得到的仿製藥來推斷返回類型爲一體,可以爲空?
這是一些測試代碼,以表明它適用於整數值:
//[StringLength(256)]
//public string Name { get; set; }
PropertyInfo info = ReflectionAPI.GetProperty<Organisation, String>(x => x.Name);//not null
StringLengthAttribute attr = info.GetAttribute<StringLengthAttribute>();//not null
int? maximumLength = attr.GetValue(x => x.MaximumLength);//256
int? minimumLength = attr.GetValue(x => x.MinimumLength);//0
PropertyInfo info2 = ReflectionAPI.GetProperty<Organisation, int>(x => x.ID);//not null
StringLengthAttribute attr2 = info2.GetAttribute<StringLengthAttribute>();//null because ID doesn't have the attribute
int? maximumLength2 = attr2.GetValue(x => x.MaximumLength);//null
int? minimumLength2 = attr2.GetValue(x => x.MinimumLength);//null
//I can use the GetProperty extension method on an instance
Organisation instance = (Organisation)null;
PropertyInfo info3 = instance.GetProperty(x => x.ToString());//null because its a method call not a property
StringLengthAttribute attr3 = info3.GetAttribute<StringLengthAttribute>();//null
int? maximumLength3 = attr3.GetValue(x => x.MaximumLength);//null
int? minimumLength3 = attr3.GetValue(x => x.MinimumLength);//null
這是我ReflectionAPI
的休息:
public static class ReflectionAPI
{
public static Nullable<R> GetValue<T, R>(this T a, Expression<Func<T, R>> expression)
where T : Attribute
{
if (a == null)
return null;
PropertyInfo p = GetProperty(expression);
if (p == null)
return null;
return (R)p.GetValue(a, null);
}
public static T GetAttribute<T>(this PropertyInfo p) where T : Attribute
{
if (p == null)
return null;
return p.GetCustomAttributes(false).OfType<T>().LastOrDefault();
}
public static PropertyInfo GetProperty<T, R>(Expression<Func<T, R>> expression)
{
if (expression == null)
return null;
MemberExpression memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
return null;
return memberExpression.Member as PropertyInfo;
}
}
我認爲可能是這種情況,喬恩。我正在使用表達式樹,因爲這似乎是人們使用lambdas而不是魔術字符串獲取PropertyInfo的最常見方式,並不是因爲我真的瞭解它。如果我答應回去再讀一遍你書中的那一章,你會告訴我一個你現在的意思的例子嗎? ;-) – Colin
@Colin:當然,將編輯該文件。 –
請注意,如果你有這兩個方法,你可以接受任何一個沒有任何約束的方法可以*除了可爲空的struct *的對象。您需要添加第三個重載,其中'T'是一個可以爲空的結構以真正獲取所有內容。 – Servy