簡體   English   中英

C#獲取C#中某個類型對象的所有屬性

[英]C# get all properties of a certain type of an object in C#

我有一個包含 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 傳遞給列表,或者我是否必須在 Car 對象中操作使用它們。

我忘了說我正在添加它們

圖像。添加(汽車。圖像1);

但是我的代碼越來越亂了。 因為我必須檢查空值和許多其他事情。 如果我可以在循環中獲取 IFormFile,我的生活就會容易得多。

下面的代碼演示了如何從對象car獲取IFormFile類型的所有屬性。

正如評論中提到的,反射 API 很慢 - 考慮緩存PropertyInfo對象,或者更好的 - 使用表達式來編譯委托,它將迭代對象屬性並將它們的值放入目標集合中。

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 |

這是一個從提供的對象返回指定類型的所有屬性的方法:

public static List<TProperty> GetAllPropertyValuesOfType<TProperty>(this object obj)
{
    return obj.GetType()
        .GetProperties()
        .Where(prop => prop.PropertyType == typeof(TProperty))
        .Select(pi => (TProperty)pi.GetValue(obj))
        .ToList();
}

你可以這樣使用它:

Car myCar;
List<IFormFile> imagesOfMyCar = myCar.GetAllPropertyValuesOfType<IFormFile>();

您可能正在使用反射。 GetProperties 方法返回所有特定類型的屬性。

例如,您的代碼必須如下:

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    public class Car
    {

        public IFormFile Imagem1 { get; set; }
        public IFormFile Imagem2 { get; set; }
        public IFormFile Imagem3 { get; set; }
        //and etc
    }

    public class Example
    {
        public static void Main()
        {
            List<IFormFile> imagens = new List<IFormFile>();

            var car = new Car();

            var carType = car.GetType();
            var ifromFileProperties = carType.GetProperties().Where(x => x.PropertyType == typeof(IFormFile)).ToArray();

            foreach (var property in ifromFileProperties)
            {
                var image = (IFormFile)property.GetValue(car, null);
                imagens.Add(image);
            }
        }
    }
}

最后在列表中列出了所有屬性類型為 IFormFile 的項目

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM