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 

     
  • 相关阅读:
    java基础部分的一些有意思的东西。
    antdvue按需加载插件babelpluginimport报错
    阿超的烦恼 javaScript篇
    .NET E F(Entity Framework)框架 DataBase First 和 Code First 简单用法。
    JQuery获得input ID相同但是type不同的方法
    gridview的删除,修改,数据绑定处理
    jgGrid数据格式
    Cannot read configuration file due to insufficient permissions
    Invoke action which type of result is JsonResult on controller from view using Ajax or geJSon
    Entity model数据库连接
  • 原文地址:https://www.cnblogs.com/wintersun/p/1460293.html
Copyright © 2011-2022 走看看