获取具有类似名称的属性列表以循环c#

时间:2016-12-07 08:28:49

标签: c# .net reflection

我有一个包含多个属性的类

public class Hotel
{
   public string ID {get; set;}
   public string Name {get; set;}
   public string Location {get; set;}
   public Image Image1 {get; set;}
   public Image Image2 {get; set;}
   public Image Image3 {get; set;}
   public Image Image4 {get; set;}
}

我想获取以属性名称“Image”开头的所有属性的列表 前

public List<Image> GetImageList(Hotel hotel)
{
  List<Image> imageList = new List<Image>();
  foreach(var item in <ImageList>)
  {
    rest of the code .....
  }

  return imageList ;
}

5 个答案:

答案 0 :(得分:2)

从技术上讲,作为快速而肮脏的解决方案,您可以尝试反射

   using System.Reflection;

   ...

   // Properties; some conditions like property.CanRead && property.CanWrite 
   // can well appear redundant, but since the class is not yours,
   // better be a bit paranoic esp. having run into a bad design 
   var properties = hotel
     .GetType()
     .GetProperties(BindingFlags.Public | BindingFlags.Instance)
     .Where(property => property.CanRead && property.CanWrite) // Not necessary 
     .Where(property => property.Name.StartsWith("Image"))
     .Where(property => property.PropertyType == typeof(Image)); // Not necessary

   // Properties' values, i.e. images
   List<Image> list = properties
     .Select(property => property.GetValue(hotel) as Image)
     .Where(image => image != null) // if you want to filter out nulls
     .ToList(); 

但是,现在是重新设计例程的最佳时机:

  1. 规范化数据库表(将图像推送到单独的表中)
  2. 重新设计 Image1..Image4IList<Image>或类似集合

答案 1 :(得分:1)

首先,您可以使用PropertyInfos获取所有Reflection,并在使用不同GetImageList个实例调用Hotel时重复使用它们:

private static List<PropertyInfo> hotelImages = GetHotelImageProperties();

private static List<PropertyInfo> GetHotelImageProperties()
{
    return typeof(Hotel)
        .GetProperties(BindingFlags.Instance | BindingFlags.Public)
        .Where(x => x.PropertyType == typeof(Image))
        .Where(x => x.CanRead)
        .Where(x => x.Name.StartsWith("Image"))
        .ToList();
}

然后,每次调用GetImageList时,只需获取属性的值:

public static List<Image> GetImageList(Hotel hotel)
{
    return hotelImages
        .Select(x => x.GetValue(hotel))
        .Cast<Image>()
        .ToList();
}

话虽如此,重要的是要注意 反射很慢 ,当 时,应该避免这种情况更重要的是,这些属性可能在编译时已知,或者可以表示为一些IEnumerable<Image>以允许更好的设计(更灵活,更快速和类型安全)。

如果它是从数据库或其他方案生成的,您应该考虑将其表示或生成为某种集合类型。

答案 2 :(得分:0)

以这种方式获取属性需要反思,因为反射对于性能而言并不是很好。我为你找到了一个更好的解决方案:

public class Hotel
{
    public string ID {get; set;}
    public string Name {get; set;}
    public string Location {get; set;}
    public List<Image> Images {get; set;}
}

这样你就可以使用:

Hotel hotel = new Hotel();
// Set properties
List<Image> imagesFromHotel = hotel.Images;

那不是更容易吗?您还可以更轻松地添加更多图像。您不需要为更多图像添加更多属性。

答案 3 :(得分:0)

您可以使用反射循环浏览酒店属性,并从图像类型中获取值:

public List<Image> GetImageList(Hotel hotel)
    {
        List<Image> imageList = new List<Image>();
        var type = hotel.GetType();
        var propertyInfos = type.GetProperties();
        foreach (var item in propertyInfos)
        {
            if (item.Name.StartsWith("Image") && item.PropertyType==typeof(Image))
            {
                imageList.Add((Image)item.GetValue(hotel));
            }
        }

        return imageList;
    }

答案 4 :(得分:0)

这将为您提供一个可枚举的Image序列,该序列为每个公共属性返回Image,其名称以“Image”开头:

var images =
    from   property in hotel.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
    where  property.Name.StartsWith("Image") && property.PropertyType == typeof(Image)
    select (Image) property.GetValue(hotel);