我有一个WebAPI方法,其中有一个IEnumerable<T>
个对象,其中T的类型直到运行时才知道。所以,我需要在foreach
集合上执行IEnumerable<T>
。问题是我无法用特定类型替换T,因为直到运行时才知道该类型。因此,我在辅助方法中使用一些反射得到T的类型,并将其存储到变量&#34; type&#34;中。但显然,我不能使用IEnumerable<type>
。它会抛出一个错误,指出变量不能用作类型。
每当某些类型的数据发生更新时,我的WebAPI方法都需要记录活动。所以,我有一个自定义的ActionFilter属性设置来执行脏工作。
这是我的WebAPI方法(这只是一个虚拟测试方法):
[HttpPost]
[Route("testlogging")]
[PhiLog]
public IEnumerable<Person> UpdateTestData(Person person)
{
IList<Person> persons = new List<Person>();
persons.Add( person );
persons.Add( person );
return persons;
}
执行OnActionExecuted时,我们不知道返回给调用者的响应内容的类型。它可以只是null,或者只是一个字符串,或者只是一个int或IList<T>
或IEnumerable<T>
,并且T的类型是未知的。这是我的自定义属性:
public class PhiLogAttribute : ActionFilterAttribute
{
public override void OnActionExecuted( HttpActionExecutedContext actionExecutedContext )
{
var user = AuthenticationHelper.GetCurrentUserFromRequest( actionExecutedContext.Request );
var actionDescriptor = actionExecutedContext.Request.GetActionDescriptor();
var controllerName = actionDescriptor.ControllerDescriptor.ControllerName;
var methodName = actionDescriptor.ActionName;
var action = string.Format( "{0}/{1}", controllerName, methodName );
var responsePayload = actionExecutedContext.Response.Content as ObjectContent;
var payloadType = responsePayload.ObjectType;
/* The variable below (payloadObj) could be of any type - an int, a
string or a generic ICollection. The code below is just assuming
it is of type IList<Person>. This is for my test purpose */
var payloadObj = responsePayload.Value;
/* AppHelper.GetEnumerableType returns the type of the generic
parameter T. In this case, a Person type */
var type = AppHelper.GetEnumerableType( payloadObj.GetType());
if ( payloadType.GetInterfaces().Any( x => x.GetType().Name == "ICollection`1") )
{
/* This is where I am stumped. I need to walk this
ICollection<T> and log some value from few properties of T.
At runtime, payloadObj is of type object. I need to cast it
into the correct ICollection type */
foreach (var x in (ICollection<type>)payloadObj)
{
//do something with var x here.
/* But ICollection<type> throws an error "type is a variable
but used like a type" */
}
}
}
}
这是我的帮助方法,用于获取类型参数T的类型。
public static Type GetEnumerableType( Type type )
{
var interfaceTypes = type.GetInterfaces();
foreach ( Type interfaceType in interfaceTypes )
{
if ( interfaceType.IsGenericType && interfaceType.Name == "ICollection`1" )
return interfaceType.GetGenericArguments()[ 0 ];
}
return null;
}
我在问题所在的代码中注释了内联。有人请告诉我如何在IEnumerable<T>
中使用变量代替T.感谢。
答案 0 :(得分:2)
如何在
IEnumerable<T>
中使用变量代替T?
你做不到。必须在编译时知道泛型类型参数。
幸运的是,在您的特定场景中,有一个简单的替代方案。由于ICollection<T>
接口继承了非 - 通用IEnumerable
接口,因此您只需将对象转换为IEnumerable
并枚举:
// using System.Collections;
foreach (object x in (IEnumerable)payloadObj)
{
// Access properties of x using reflection or by casting to a known type...
}