我有一个具有10个IFormFiles的对象。我想将它们放入IFormFile列表中,以便可以轻松进行操作。
public class Car{
public IFormFile Imagem1 {get; set;}
public IFormFile Imagem2 {get; set;}
......
}
List<IFormFile> imagens = new List<IFormFile>();
foreach(IFormFile imagem in carro.)
{
imagens.add(...);
}
有没有一种方法可以将IFormFile传递给lista,或者我必须操纵在Car对象中使用它们。
我忘了说我是用
images.add(car.Image1);
但是我的代码变得混乱了。因为我必须检查null和许多其他内容。如果我可以循环获得IFormFile,那么我的生活会容易得多。
下面的代码演示了如何IFormFile
从对象获取type的所有属性car
。
正如评论中提到的那样,Reflection API相当慢-考虑缓存PropertyInfo
对象,或者更好的方法-使用Expressions编译委托,这将遍历对象属性并将其值放入目标集合。
void Main()
{
var car = new Car();
var imagens = typeof(Car).GetProperties()
.Where(x => x.PropertyType == typeof(IFormFile))
.Select(x => (IFormFile)x.GetValue(car))
.Where(x => x != null)
.ToList();
}
下面是如何将上面的代码转换为使用缓存PropertyInfo
对象的示例:
void Main()
{
var car = new Car();
var imagens = PropertyGetter<Car, IFormFile>.GetValues(car);
}
public static class PropertyGetter<TObject, TPropertyType>
{
private static readonly PropertyInfo[] _properties;
static PropertyGetter()
{
_properties = typeof(TObject).GetProperties()
// "IsAssignableFrom" is used to support derived types too
.Where(x => typeof(TPropertyType).IsAssignableFrom(x.PropertyType))
// Check that the property is accessible
.Where(x => x.GetMethod != null && x.GetMethod.IsPublic && !x.GetMethod.IsStatic)
.ToArray();
}
public static TPropertyType[] GetValues(TObject obj)
{
var values = _properties
.Select(x => (TPropertyType) x.GetValue(obj))
.ToArray();
return values;
}
}
另一个示例说明如何实现基于表达式选择特定类型的属性值的逻辑。
public static class PropertyGetterEx<TObject, TPropertyType>
{
private static readonly Func<TObject, TPropertyType[]> _getterFunc;
static PropertyGetterEx()
{
// The code below constructs the following delegate:
//
// o => object.ReferenceEquals(o, null)
// ? null
// : new TPropertyType[] { o.Prop1, o.Prop2, ... };
//
// An expression for the parameter `o`
var objParam = Expression.Parameter(typeof(TObject), "o");
// Create expressions for `o.Prop1` ... `o.PropN`
var propertyAccessExprs = GetPropertyInfos()
.Select(x => Expression.MakeMemberAccess(objParam, x));
// Create an expression for `new TPropertyType[] { o.Prop1, o.Prop2, ... }`
var arrayInitExpr = Expression.NewArrayInit(
typeof(TPropertyType),
propertyAccessExprs);
// Create an expression for `object.ReferenceEquals(o, null)`
var refEqualsInfo = typeof(object).GetMethod(nameof(object.ReferenceEquals));
var refEqualsExpr = Expression.Call(
refEqualsInfo,
objParam,
Expression.Constant(null, typeof(TPropertyType)));
// The condition expression
var conditionExpr = Expression.Condition(
refEqualsExpr,
Expression.Constant(null, typeof(TPropertyType[])),
arrayInitExpr);
_getterFunc = Expression
.Lambda<Func<TObject, TPropertyType[]>>(
conditionExpr,
objParam)
.Compile();
}
private static PropertyInfo[] GetPropertyInfos()
{
var properties = typeof(TObject).GetProperties()
// "IsAssignableFrom" is used to support derived types too
.Where(x => typeof(TPropertyType).IsAssignableFrom(x.PropertyType))
// Check that the property is accessible
.Where(x => x.GetMethod != null && x.GetMethod.IsPublic && !x.GetMethod.IsStatic)
.ToArray();
return properties;
}
public static TPropertyType[] GetValues(TObject obj)
{
return _getterFunc(obj);
}
}
以下是上面提供的3种方法的基准测试结果(无缓存,带PropertyInfo缓存,基于表达式)。不出所料,基于表达式的解决方案的性能要比其他解决方案好得多:
| Method | Mean | Error | StdDev | Rank |
|--------------------- |----------:|---------:|---------:|-----:|
| NoCache | 789.99 ns | 4.669 ns | 4.139 ns | 3 |
| PropertyInfoCache | 417.32 ns | 3.271 ns | 3.059 ns | 2 |
| ExpressionBasedCache | 27.55 ns | 0.091 ns | 0.085 ns | 1 |
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句