分享
 
 
 

Asp.net下的对象成员数据绑定器实现

王朝asp·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

用过MonoRail的朋友应该知道它提供的对象成员数据绑定功能非常方便,通过标记参数属性或方法就可以自动把提交回来的数据和对象成员进行绑定;有了这些方便的功能的确可以节省大量的set代码。不过这些功能只是MonoRail提供,于是实现类似的功能方便自己开发。

实现目标:

可以灵活方便地实现数据绑定。

OrderSearch search = FormContext.BindObject<OrderSearch>();

Orders order = FormContext.BindObject<Orders>("order");

制定规则和约束

首先确定WEB提交的数据和成员属性的映射关系,可以通过名称约定的方式:

<input id="Text1" name="companyname" type="text" />

xxxx.LastName、xxxx_LastName或xxxxLastName等。在绑过程可以指定前缀进行对象成员的绑定;不过在webForm控件的Name是asp.net生成的,在关系分析上就相对复杂些。

类型转换接口的定义

因为转换的情况是很难确定;除了。NET的基础类型外实际应用中还会存在其他转换方式,如:HttpPostedFile到byte[],序列化String到Object等。因此制定转换接口就可以方便实现可扩展和可配置。

public interface IStringConverter

{

object ConvertTo(string value, out bool succeeded);

}

由于Web提供的数据大部份是以string的方式提供,因此定义一个基于string转换描述。基于接口的实也很简单:

public class ToSbyte :IStringConverter

{

#region IStringConverter 成员

object IStringConverter.ConvertTo(string value, out bool succeeded)

{

sbyte nvalue;

succeeded = sbyte.TryParse(value, out nvalue);

return nvalue;

}

#endregion

}

IStringConverter工厂的实现

由于转换情况的不确定性,因此通过工厂的方式来达到代码对外的封闭性和良好的扩展性。可以通过目标类型来获取相关转换实例,在.NET中IDictionary就能够达到应用的要求。

static IDictionary<Type, IStringConverter> mConverters;

public static IDictionary<Type, IStringConverter> Converters

{

get

{

if (mConverters == null)

{

lock (typeof(ConverterFactory))

{

OnInit();

}

}

return mConverters;

}

}

static void OnInit()

{

if (mConverters != null)

return;

mConverters = new Dictionary<Type, IStringConverter>();

mConverters.Add(typeof(byte), new ToByte());

LoadConfig();

}

//从配置文件加载转换器映射,如果配置存在相同类型转器就取代原有转换器

static void LoadConfig()

{

//Load Config

// <converter type="System.Int32",value="HFSoft.Binder.ToByte"

}

为了方便使用可以在工厂中硬编码配置内部基础类型;因为转换情况的不确定,所以允许通过配置文件的方式引入不同情况的类型转换器。

可以扩展性的Custom Attribute

虽然工厂可以达到转换接口的可配置性,但实际上很难达到应用要求;在某些情况下类型转换器只是在某些对象成员中有效(虽然配置文件也可以达到期要求,但在配置文件中定义这么小的粒度并不是好的选择);通过Attribute给相关Property指定类型转换器非常适合。

/// <summary>

/// 用于特殊情况下描述对象具体成员的转换器

/// </summary>

[AttributeUsage(AttributeTargets.Property)]

public class ConverterAttribute : Attribute, IStringConverter

{

public ConverterAttribute(Type convertertype)

{

mConverterType = convertertype;

}

public ConverterAttribute(Type convertertype, string defvalue)

{

mConverterType = convertertype;

mDefaultValue = defvalue;

}

private Type mConverterType;

public Type ConverterType

{

get

{

return mConverterType;

}

}

private String mDefaultValue;

public String DefaultValue

{

get

{

return mDefaultValue;

}

set

{

mDefaultValue = value;

}

}

protected IStringConverter CreateInstance()

{

if (mConverters.ContainsKey(ConverterType))

return mConverters[ConverterType];

lock (typeof(ConverterAttribute))

{

if (!mConverters.ContainsKey(ConverterType))

{

mConverters.Add(ConverterType, (IStringConverter)Activator.CreateInstance(ConverterType));

}

return mConverters[ConverterType];

}

}

static IDictionary<Type, IStringConverter> mConverters = new Dictionary<Type, IStringConverter>();

#region IStringConverter 成员

public object ConvertTo(string value, out bool succeeded)

{

string newvalue = value != null ? value : DefaultValue;

return CreateInstance().ConvertTo(newvalue, out succeeded);

}

#endregion

}

通过ConverterAttribute可以方便制定粒度更小的配置

private byte[] mFileStream;

[Converter(typeof(FileStreamConverter),"IconPhoto")]

public byte[] FileStream

{

get

{

return mFileStream;

}

set

{

mFileStream = value;

}

}

以上定义可以上传文件流转成byte[]到FileStream属性中。

功能集成实现

现在就把所有东西集成起来,满足目的的要求。

public object Bind(System.Collections.Specialized.NameValueCollection values, string prefix)

{

object newobj = Activator.CreateInstance(ObjectType);

if (prefix == null)

prefix = "";

object value;

foreach (PropertyInfo item in Properties)

{

value = values[prefix + "." + item.Name];

if(value == null)

value = values[prefix + "_" + item.Name];

if(value == null)

value = values[prefix + item.Name];

BindProperty(newobj, item, (string)value);

}

return newobj;

}

private void BindProperty(object obj, PropertyInfo property, string value)

{

IStringConverter stringconver;

object nvalue;

bool confirm = false;

Object[] cas = property.GetCustomAttributes(typeof(ConverterAttribute), true);

if (cas.Length > 0)

{

nvalue = ((ConverterAttribute)cas[0]).ConvertTo(value, out confirm);

if (confirm)

mPropertiesHandle[property].SetValue(obj, nvalue);

}

else

{

if (ConverterFactory.Converters.ContainsKey(property.PropertyType))

{

stringconver = ConverterFactory.Converters[property.PropertyType];

nvalue = stringconver.ConvertTo(value, out confirm);

if (confirm)

mPropertiesHandle[property].SetValue(obj, nvalue);

}

}

}

因为Web提交的数据几乎可以通过HttpRequest.Params得到,只需要根据属性名称和相关前缀进行匹配查找就可以了。这里实现的匹配方式并不理想,其实可以在相关page第一次请求就可以分析到关系存在IDictionary中,后期直接使用就可以了。

以上功能是在编写一个MVC组件的数据绑定功能,其实完全可以移植传统的WebForm下工作;有更好想法的朋友请多提交意见。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有