zoukankan      html  css  js  c++  java
  • 泛型小记与泛型Dictionary使用Enum

          泛型的应用无处不在,下面是项目代码片断,比较典型的泛型与反射应用,提供了类型安全.场景是项目中有基于exchange访问,使用了Exchange Web Services Manage API,我们需要写一个辅助查询的Enum属性类,以Dictionary的方式,Enum类型对Key,string类型为Value.最后转换成Manage API中具体查询类.

        public enum ContactQueryEnum
        {
            DisplayName,
            NickName,
            CompleteName

            }

    好的,下面是转换方法:

    /// <summary>
    /// Gets the EWS's Entity property auto conver to dictionary.
    /// </summary>
    /// <typeparam name="T">first dictionary key</typeparam>
    /// <typeparam name="K">second dictionary key</typeparam>
    /// <typeparam name="V">first dictionary value</typeparam>
    /// <typeparam name="U">second dictionary value</typeparam>
    /// <param name="dictionary">The dictionary.</param>
    /// <returns>IDictionary<PropertyDefinitionBase, U></returns>
    /// <remark>Author : PetterLiu 2008-12-24 15:11 </remark>
    public static IDictionary<PropertyDefinitionBase, U> GetEWSProperty<T, K, V, U>(IDictionary<K, V> dictionary)
    {
        if (dictionary != null)
        {
            IDictionary<PropertyDefinitionBase, U> queryparams = new Dictionary<PropertyDefinitionBase, U>();
            FieldInfo[] fieldInfosItem = typeof(ItemSchema).GetFields(BindingFlags.Public | BindingFlags.Static);
            FillParamsDictionary<K, V, U>(fieldInfosItem, dictionary, queryparams);
    
            if (typeof(T) != typeof(ItemSchema))
            {
                FieldInfo[] fieldInfosT = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static);
                FillParamsDictionary<K, V, U>(fieldInfosT, dictionary, queryparams);
            }
            return queryparams;
        }
        return null;
    }
    
    #region FillParamsDictionary
    /// <summary>
    /// Fills the params dictionary.
    /// </summary>
    /// <typeparam name="K">second dictionary key</typeparam>
    /// <typeparam name="V">first dictionary value</typeparam>
    /// <typeparam name="U">second dictionary value</typeparam>
    /// <param name="fieldInfos1">The field infos1.</param>
    /// <param name="dictionary">The dictionary.</param>
    /// <param name="queryparams">The queryparams.</param>
    /// <remark>Author : PetterLiu 2008-12-24 15:11 </remark>
    private static void FillParamsDictionary<K, V, U>(FieldInfo[] fieldInfos1, IDictionary<K, V> dictionary,
        IDictionary<PropertyDefinitionBase, U> queryparams)
    {
        foreach (var info in fieldInfos1)
        {
            foreach (var pair in dictionary)
            {
                if (pair.Key.ToString() == info.Name)
                {
                    PropertyDefinitionBase propertyDefinitionBase = info.GetValue(info) as PropertyDefinitionBase;
                    queryparams.Add(propertyDefinitionBase, (U)(object)pair.Value);
                }
            }
        }
    } 
    #endregion
    PropertyDefinitionBase,ItemSchema是Exchange Web Services Manage API中的类,UnitTest:
    /// <summary>
    /// Entities the convert reflection test.
    /// </summary>
    /// <remarks>author:Petter Liu http://wintersun.cnblogs.com </remarks>
    [Test]
    public void EntityConvertReflectionTest()
    {
        var searchparams = DictionaryHelper.CreateEnumKeyDictionaryInstance<ContactQueryEnum, string>();
        searchparams.Add(ContactQueryEnum.BusinessAddressCity, "ShangHai");
        searchparams.Add(ContactQueryEnum.CompanyName, "ABC");
    
        IDictionary<PropertyDefinitionBase, string> searchpropertydic =
        ConvertUtlity.GetEWSProperty<ContactSchema, ContactQueryEnum, string, string>(searchparams);
        foreach (var filter in searchpropertydic)
        {
            //if search value was not null and empty,then add search parameter
            if (!string.IsNullOrEmpty(filter.Value))
            {
                Trace.Write(string.Format("Key:{0}", filter.Key));
                Trace.WriteLine(string.Format("   Value:{0}", filter.Value));
                Assert.IsInstanceOf<PropertyDefinitionBase>(filter.Key);
                Assert.IsInstanceOf<string>(filter.Value);
            }
        }
        Assert.AreEqual(2, searchpropertydic.Count);
    }
    另一个值得关注的细节,当我们使用Enum类型作为key值时,Dictionary的内部操作就需要将Enum类型转换为System.Object,这就导致了性能问题。
    注意上面代码还有一个方法DictionaryHelper.CreateEnumKeyDictionaryInstance,这是专门为Enmu做key时Dictionary性能优化类.
    public class DictionaryHelper
    {
        /// <summary>
        /// Creates the enum key dictionary instance.
        /// </summary>
        /// <typeparam name="K">K</typeparam>
        /// <typeparam name="V">V</typeparam>
        /// <returns>IDictionary with key and value</returns>
        /// <remarks>author PetterLiu http://wintersun.cnblogs.com </remarks>
        public static IDictionary<K, V> CreateEnumKeyDictionaryInstance<K, V>() where K : struct
        {
            return new Dictionary<K, V>(new EnumComparer<K>());
        }
    }
    关于EnumComparer可参考在Dictionary中使用枚举,以及Accelerating Enum-Based Dictionaries with Generic EnumComparer
    下面还是放上这个关键代码,利用C# 3.0中Lambda表达式:
    /// <summary>
    /// EnumComparer
    /// </summary>
    /// <typeparam name="T">struct</typeparam>
    /// <example>
    /// <code>
    /// <![CDATA[
    ///     public enum DayOfWeek{//...}
    ///     var dictionary = new Dictionary<DayOfWeek, int>(new EnumComparer<DayOfWeek>());
    /// ]]>  
    /// </code>
    /// </example>
    public class EnumComparer<T> : IEqualityComparer<T> where T : struct
    {
        /// <summary>
        /// Equalses the specified first.
        /// </summary>
        /// <param name="first">The first.</param>
        /// <param name="second">The second.</param>
        /// <returns>bool</returns>
        public bool Equals(T first, T second)
        {
            var firstParam = Expression.Parameter(typeof(T), "first");
            var secondParam = Expression.Parameter(typeof(T), "second");
            var equalExpression = Expression.Equal(firstParam, secondParam);
    
            return Expression.Lambda<Func<T, T, bool>>
                (equalExpression, new[] { firstParam, secondParam }).
                Compile().Invoke(first, second);
        }
    
        /// <summary>
        /// Gets the hash code.
        /// </summary>
        /// <param name="instance">The instance.</param>
        /// <returns>int</returns>
        public int GetHashCode(T instance)
        {
            var parameter = Expression.Parameter(typeof(T), "instance");
            var convertExpression = Expression.Convert(parameter, typeof(int));
    
            return Expression.Lambda<Func<T, int>>
                (convertExpression, new[] { parameter }).
                Compile().Invoke(instance);
        }
    }
     
    小结:后期试着用AutoMapper来实现转换,发现对于这个多个类型关联转换,以及原生类设计特别性,没有能够成功.代码中随时存在这些小细节,
    对于这些细节我们不能忽视.
    Author: Petter Liu   http://wintersun.cnblogs.com 

     
  • 相关阅读:
    GridView与ArrayAdapter的结合
    翻翻git之---闪烁动画的TextView RevealTextView
    希捷硬盘扩容软件-----DiscWizard
    项目管理的酸甜苦辣
    【转】Bootloader之uBoot简介(转)
    【转】uboot移植(一)BootLoader基本概念
    【转】U-boot分析与移植(1)----bootloader分析
    【转】MIPS交叉编译环境的建立
    【转】RTSP实例解析
    【转】Eclipse快捷键 10个最有用的快捷键----不错
  • 原文地址:https://www.cnblogs.com/wintersun/p/1460293.html
Copyright © 2011-2022 走看看