场景:
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;
}
作者:MaoBisheng
出处:http://maobisheng.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://maobisheng.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。