C#中dynamic类型作为泛型参数传递过去后,反射出来的对象类型是object,我用老外的这篇博文中的代码跑起来,得出的结果是:Flying using a Object map (a map),将Fly<T>(T map)方法的代码改为如下代码,即可获取dynamic对象的原始类型:
Type t = typeof(T);
if (t == typeof(object))
{
t = map.GetType();
}
Console.WriteLine("Flying using a {0} map ({1})", t.Name, map);
实际项目中用到了MvcContrib,在调用OrderBy时传入的是IQueryable<dynmaic>对象,反射此类对象的属性时,会报异常,MvcContrib.Sorting中代码是这样的:
public static IQueryable<T> OrderBy<T>(this IQueryable<T> datasource, string propertyName, SortDirection direction)
{
if(string.IsNullOrEmpty(propertyName))
{
return datasource;
}
var type = typeof(T);
var property = type.GetProperty(propertyName); //这里报异常
if(property == null)
{
throw new InvalidOperationException(string.Format("Could not find a property called '{0}' on type {1}", propertyName, type));
}
var parameter = Expression.Parameter(type, "p");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExp = Expression.Lambda(propertyAccess, parameter);
const string orderBy = "OrderBy";
const string orderByDesc = "OrderByDescending";
string methodToInvoke = direction == SortDirection.Ascending ? orderBy : orderByDesc;
var orderByCall = Expression.Call(typeof(Queryable),
methodToInvoke,
new[] { type, property.PropertyType },
datasource.Expression,
Expression.Quote(orderByExp));
return datasource.Provider.CreateQuery<T>(orderByCall);
}
原因是调用此方法时,如果传入的泛型是dynamic,typeof(T)得出的结果是object,接下来的property将会出异常。
解决的办法是:在 var type = typeof(T); 后面加一段判断语句,代码如下:
var type = typeof(T);
if(type == typeof(object))
{
type = datasource.FirstOrDefault().GetType();
}
这样就可以获取IQueryable<dynmaic>的原始类型。 |