65.9K
CodeProject 正在变化。 阅读更多。
Home

在 ASP.NET 中使用属性和反射实现对比表。

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.23/5 (13投票s)

2003 年 10 月 13 日

3分钟阅读

viewsIcon

73429

downloadIcon

838

一个通用的方案,用于在 ASP.NET 中使用属性和反射比较一个类的多个实例的属性。

引言

大多数在线商店都支持一项功能,用户可以选择来自不同供应商的多个产品并进行比较。例如,在 http://www.sonystyle.com/ 中,用户可以选择数码相机中提供的不同型号,并在它们之间进行比较。此比较表基本上列出了用户将在数码相机中寻找的关键功能,并显示每个型号的功能。下面显示了此类比较表的示例

Comparison Table in Www.SonyStyle.com

最近,我正在阅读我们的一位业务人员提出的要求,我意识到它与这些网站上显示的比较表类似。由于开发平台是 .NET,我决定利用 .NET 的功能。

问题定义

  • 用户必须能够选择不同的对象并比较它们的属性。比较的对象始终是同一类型。
  • 必须能够在其他现有和新的 Web 应用程序中重用此实现。

目标

  • 通用方案,以便可以在多个项目中重用它。
  • 方案应该简单、易于理解、可扩展和可定制。

使用的功能

经过一段时间的思考,我决定使用 .NET 的以下功能来实现目标。

  • 属性
  • Reflection(反射)
  • Web 自定义控件 (ASP.NET)

方案如何运作

我定义了一个名为 CompareAttribute 的属性,它有两个属性,分别是 DisplayTitleDisplayOrder。任何属性需要在比较表中列出的类都应该用这个属性来装饰。

    [AttributeUsage(AttributeTargets.Property)]
    public class CompareAttribute : System.Attribute
    {
        private int __displayOrder = 0;
        private string __displayName = string.Empty;
  
         public CompareAttribute(int DisplayOrder, string DisplayName)
        {
            __displayOrder = DisplayOrder;
            __displayName = (DisplayName == null) ? "<undefined>" : 
                  DisplayName.Trim();
        }
  
        public int DisplayOrder
        {
            get
            {
                return __displayOrder;
            }
        }

        public string DisplayName
        {
            get
            {
                return __displayName;
            }
        }
    }

我定义了一个名为 DiffTable 的 Web 自定义控件,它包含呈现比较表的逻辑。这个自定义控件公开了一个名为 ObjectsToCompare 的属性,类型为 ArrayList。如果您提供一个包含您要比较的对象列表的 arraylist,那么控件将执行必要的魔法并显示 Comparison 表。

为了说明这个方案,我定义了一个名为 Camera 的示例类。这个 Camera 类有五个属性 - NameModelPriceWarrantyHasCarlZeiss。我用 compare 属性装饰了每个属性。

用 compare 属性装饰的类属性看起来像

    [Compare(5, "Warranty Info")]
        public string Warranty
        {
            get
            {
                return __warranty;
            }
            set
            {
                __warranty = (value == null) ? string.Empty : value.Trim();
            }
        }

自定义控件使用反射来识别正在比较的对象的类型。 此外,它还确保用户至少分配了 2 个对象实例以进行比较。

    private SortedList FetchComparableProperties(Type type)
        {
            SortedList prps = new SortedList(32);
            CompareAttribute cmp = null;
   
            foreach(PropertyInfo prpInfo in type.GetProperties())
            {
                cmp = (CompareAttribute)Attribute.GetCustomAttribute(
                     prpInfo, typeof(CompareAttribute));
                if(cmp != null)
                {
                    if(prps.ContainsKey(cmp.DisplayOrder))
                        throw new Exception(string.Format(
                           "A property with the same display" + 
                           " order of {0} already exists.", 
                            cmp.DisplayOrder));
                    prps.Add(cmp.DisplayOrder, prpInfo);
                }
            }

            return prps;
        }

自定义控件中的上述代码显示了用于识别标记有 CompareAttribute 的属性,并根据 compare 属性装饰中指定的 Display Order 值按排序顺序排列属性的逻辑。

下载包含一个示例 Web 应用程序,该应用程序显示由此方案生成的比较表。 下载还包含 Web 自定义控件的源代码。 我已在 Web 自定义控件中的每个函数中添加了足够的文档,以便于理解。

Sample Comparison Table Output

亮点

  • 由于此方案基于元数据,因此即使将来向解决方案添加新类,只需使用 compare 属性装饰属性即可启用此类的实例进行比较,而无需更改现有代码。
  • 由于核心逻辑是作为 Web 自定义控件实现的,因此它是独立的且易于分发。 此控件可以在多个 Web 应用程序中重用。

改进

  1. 可以扩展此方案以支持分组比较 - 相关属性将分组在标题下(类似于 http://www.dealtime.com/ 中的功能)。
  2. 通过添加 ImageUrl 等属性,可以在比较表中显示每个被比较对象的图像。
  3. 以及更多...

结论

要在经典的 ASP 中实现类似的功能,这将非常繁琐且耗时。 在 .NET 框架的帮助下,事情变得非常容易,并且可以在短时间内实现。 我认为每个人都会意识到 .NET 让我们的生活变得更加轻松。

© . All rights reserved.