泛型的应用无处不在,下面是项目代码片断,比较典型的泛型与反射应用,提供了类型安全.场景是项目中有基于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 

 
posted on 2009-05-19 15:47  PetterLiu  阅读(1925)  评论(1编辑  收藏  举报