static IDictionary mConverters;
public static IDictionary Converters
{
get
{
if (mConverters == null)
{
lock (typeof(ConverterFactory))
{
OnInit();
}
}
return mConverters;
}
}
static void OnInit()
{
if (mConverters != null)
return;
mConverters = new Dictionary();
mConverters.Add(typeof(byte), new ToByte());
LoadConfig();
}
//从配置文件加载转换器映射,如果配置存在相同类型转器就取代原有转换器
static void LoadConfig()
{
//Load Config
为了方便使用可以在工厂中硬编码配置内部基础类型;因为转换情况的不确定,所以允许通过配置文件的方式引入不同情况的类型转换器。
可以扩展性的Custom Attribute
虽然工厂可以达到转换接口的可配置性,但实际上很难达到应用要求;在某些情况下类型转换器只是在某些对象成员中有效(虽然配置文件也可以达到期要求,但在配置文件中定义这么小的粒度并不是好的选择);通过Attribute给相关Property指定类型转换器非常适合。
///
/// 用于特殊情况下描述对象具体成员的转换器
///
[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 mConverters = new Dictionary();
#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下工作;有更好想法的朋友请多提交意见。
来源:http://www.cnblogs.com/henryfan/archive/2007/02/03/638777.html