MaoBisheng

Asp.Net(C#) & SQL & Oracle

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

场景:

    WebService中的传入/传出参数是一个字段非常多的一个对象,我们往往是在业务逻辑层来引用WebService,而值是从页面层传入的,因此需要自己定义一个实体,来实现页面层往业务逻辑层之间的传值。

如果两个实体之间字段非常多的话,可以利用反射来实现两个实体之间的转换。

 

首先,我们自定义一个Attribute,用于表示实体中某个属性,在WSDL中的名称(WSDL中的属性名称与自定义的不一定一致,比如用Java开发的WebService,在C#中调用,属性的编码规范不一样):

[AttributeUsage(AttributeTargets.All, AllowMultiple=true)]
public class WSDLFieldNameAttribute : Attribute
{      
    public string FieldName
    {
        get;
        set;
    }
 
    public Type FieldType
    {
        get;
        set;
    }
 
    public WSDLFieldNameAttribute(string Field)
    {
        FieldName = Field;
        FieldType = typeof(string);
    }
    public WSDLFieldNameAttribute(string Field, Type type)
    {
        FieldName = Field;
        FieldType = type;
    }
}

使用方法:

[WSDLFieldNameAttribute("fromDate")]
[Description("开始日期,格式“yyyyMMdd”")]
public string FromDate
{
    get;
    set;
}

转换类:

public static class WSDLFieldMappingUtil
{
    /// <summary>
    /// fill wsdl entity from entity
    /// </summary>
    /// <param name="wsdlObject"></param>
    /// <param name="entity"></param>
    public static void FillInWSDLEntity(object wsdlObject, object entity)
    {
        Type wsdlType = wsdlObject.GetType();
        Type entityType = entity.GetType();

        PropertyInfo wsdlProperty;
        PropertyInfo[] pi = entityType.GetProperties();

        foreach (PropertyInfo entityProperty in pi)
        {
            WSDLFieldNameAttribute[] myAttribute = (WSDLFieldNameAttribute[])entityProperty.GetCustomAttributes(typeof(WSDLFieldNameAttribute), false);
            if (myAttribute.Length == 0)
            {
                continue;
            }

            if (entityProperty.PropertyType.IsEnum)
            {
                if (myAttribute.Length == 1 && myAttribute[0].FieldType == typeof(string))
                {
                    wsdlProperty = wsdlType.GetProperty(myAttribute[0].FieldName);
                    if (wsdlProperty == null)
                        continue;

                    var value = entityProperty.GetValue(entity, null);
                    if (value != null)
                    {
                        wsdlProperty.SetValue(wsdlObject, EnumAttributeHelper.GetSqlByEnum(value), null);
                    }
                }
                else
                {
                    throw new Exception(string.Empty);
                }
            }
            else
            {
                wsdlProperty = wsdlType.GetProperty(myAttribute[0].FieldName);
                if (wsdlProperty == null)
                    continue;

                var value = entityType.GetProperty(entityProperty.Name).GetValue(entity, null);
                if (value != null)
                {
                    if (wsdlProperty.PropertyType != entityProperty.PropertyType)
                    {
                        if (wsdlProperty.PropertyType.IsEnum)
                        {
                            value = Enum.Parse(wsdlProperty.PropertyType, value.ToString());
                        }
                        else if (entityProperty.PropertyType == typeof(DateTime))
                        {
                            value = ((DateTime)value).ToString("yyyyMMdd");
                        }
                        else
                        {
                            value = Convert.ChangeType(value, wsdlProperty.PropertyType);
                        }
                    }

                    wsdlProperty.SetValue(wsdlObject, value, null);
                }
                else
                {
                    if (wsdlProperty.PropertyType == typeof(string))
                    {
                        wsdlProperty.SetValue(wsdlObject, "", null);
                    }
                }
            }
        }
    }

    /// <summary>
    /// fill entity from wsdl entity
    /// </summary>
    /// <param name="wsdlObject"></param>
    /// <param name="entity"></param>
    public static void FillInEntityFromWSDLObject(object entity, object wsdlObject)
    {
        if (wsdlObject == null)
            return;

        Type wsdlType = wsdlObject.GetType();
        Type entityType = entity.GetType();

        PropertyInfo wsdlProperty;
        PropertyInfo[] pi = entityType.GetProperties();

        foreach (PropertyInfo entityProperty in pi)
        {
            WSDLFieldNameAttribute[] myAttribute = (WSDLFieldNameAttribute[])entityProperty.GetCustomAttributes(typeof(WSDLFieldNameAttribute), false);
            if (myAttribute.Length == 0)
            {
                continue;
            }

            if (entityProperty.PropertyType.IsEnum)
            {
                if (myAttribute.Length == 1 && myAttribute[0].FieldType == typeof(string))
                {
                    wsdlProperty = wsdlType.GetProperty(myAttribute[0].FieldName);
                    if (wsdlProperty == null)
                        continue;

                    var value = wsdlProperty.GetValue(wsdlObject, null);
                    if (value != null && value.ToString() != "")
                    {
                        entityProperty.SetValue(entity, EnumAttributeHelper.GetEnumBySqlValue(entityProperty, value.ToString()), null);
                    }
                }
                else
                {
                    throw new Exception(string.Empty);
                }
            }
            else
            {
                wsdlProperty = wsdlType.GetProperty(myAttribute[0].FieldName);
                if (wsdlProperty == null)
                    continue;

                var value = wsdlProperty.GetValue(wsdlObject, null);
                if (value != null)
                {
                    if (value.ToString() == "")
                    {
                        if (entityProperty.PropertyType == typeof(string))
                        {
                            entityProperty.SetValue(entity, value, null);
                        }
                        continue;
                    }

                    if (wsdlProperty.PropertyType != entityProperty.PropertyType)
                    {
                        if (entityProperty.PropertyType == typeof(DateTime))
                        {
                            if (value.ToString().Length == 8)
                            {
                                value = value.ToString().Substring(0, 4) + "-" + value.ToString().Substring(4, 2) + "-" + value.ToString().Substring(6, 2);
                            }
                        }
                        value = Convert.ChangeType(value, entityProperty.PropertyType);
                    }

                    entityProperty.SetValue(entity, value, null);
                }
            }
        }
    }
}

 

上面代码需要注意的是,在某些时候,某个属性在传输的时候是以字符串的形式传输或者存储的,而在我们自定义的实体中,为了提高代码的可读性,而使用枚举

如:在数据库中存储的值分别是:O,C,P,D

public enum DcoumentStatusEnum
{
    [SqlValue("O")]
    Open = 0,
    [SqlValue("C")]
    Close = 1,
    [SqlValue("P")]
    Paid = 2,
    [SqlValue("D")]
    Delivered = 3
}

因此需要对枚举做些特殊处理,自定义一个SqlValueAttribute:

[AttributeUsage(AttributeTargets.All)]
public class SqlValueAttribute : Attribute
{
    public string Text
    {
        get;
        set;
    }
    public SqlValueAttribute(string text)
    {
        Text = text;
    }        
}

 

利用反射,根据SqlValue获取枚举,或者根据枚举获取SqlValue,性能可能会比较低,暂时也没想出什么好的办法。

public static object GetEnumBySqlValue(PropertyInfo pInfo, string sqlValue)
{
    FieldInfo[] pi = pInfo.PropertyType.GetFields();
    foreach (FieldInfo p in pi)
    {
        SqlValueAttribute[] myAttribute = (SqlValueAttribute[])p.GetCustomAttributes(typeof(SqlValueAttribute), false);
        foreach (SqlValueAttribute m in myAttribute)
        {
            if (m.Text == sqlValue.Trim())
            {
                string a = p.ToString();
                return Enum.Parse(pInfo.PropertyType, p.Name);                        
            }
        }
    }
    return null;
}
 
public static string GetSqlByEnum(object enumValue)
{
    FieldInfo[] pi = enumValue.GetType().GetFields();
    
    foreach (FieldInfo p in pi)
    {
        if (p.Name == enumValue.ToString())
        {
            SqlValueAttribute[] myAttribute = (SqlValueAttribute[])p.GetCustomAttributes(typeof(SqlValueAttribute), false);
            foreach (SqlValueAttribute m in myAttribute)
            {
                return m.Text;
            }
        }
    }
    return null;
}
posted on 2011-05-30 17:54  MaoBisheng  阅读(1207)  评论(0编辑  收藏  举报