实现WebForm下面的自动收集对象属性(与MVC下在的UpdateFrom一样)

对ASP.net MVC有了解的同学估计都对里面的UpdateFrom方法有较深的印象。它接受一个对象参数,然后,它会对任何匹配该对象的公开属性,自动对本身进行属性赋值。这样的功能都引来一片叫好声。可惜的是他只能在MVC下使用。那么在WebForm下面就不能实现这样的功能了吗?答案是可以的,其实还可以做得更好。这里把以前的代码翻出来晒晒。

我们还是先看一下UpdateFrom的实现。其实实现很简单,就是先用 反射取得对象的所有的属性。然后在Requet.QuerySting或Requet.Form中查找对应的键。如果 找到了对应的值就再调用Property.SetValue方法对其设置属性值。代码如下
public   static   void  UpdateFrom( this   object  obj, NameValueCollection values,  string  objectPrefix)
{
    Type objType 
= obj.GetType();
    
string objName = objType.Name;
    StringBuilder exceptionList 
= new StringBuilder();

    PropertyInfo[] fields 
= objType.GetProperties();

    PopulateTypeException ex 
= null;

    
foreach (PropertyInfo property in fields)
    
{

        
//check the key
        
//going to be forgiving here, allowing for full declaration
        
//or just propname
        string httpKey = property.Name;

        
if (objectPrefix != string.Empty)
            httpKey 
= objectPrefix + httpKey;

        
if (values[httpKey] == null)
        
{
            httpKey 
= objName + "." + property.Name;
        }


        
if (values[httpKey] == null)
        
{
            httpKey 
= objName + "_" + property.Name;
        }



        
if (values[httpKey] != null)
        
{
            TypeConverter conv 
= TypeDescriptor.GetConverter(property.PropertyType);
            
object value = values[httpKey];

            
if (conv.CanConvertFrom(typeof(string)))
            
{
                
try
                
{
                    value 
= conv.ConvertFrom(values[httpKey]);
                    property.SetValue(obj, value, 
null);

                }

                
catch (Exception e)
                
{
                    
string message = property.Name + " is not a valid " + property.PropertyType.Name + "" + e.Message;
                    
if (ex == null)
                        ex 
= new PopulateTypeException("Errors occurred during object binding - review the LoadExceptions property of this exception for more details");

                    PopulateTypeException.ExceptionInfo info 
= new PopulateTypeException.ExceptionInfo();
                    info.AttemptedValue 
= value;
                    info.PropertyName 
= property.Name;
                    info.ErrorMessage 
= message;

                    ex.LoadExceptions.Add(info);

                }

            }

            
else
            
{
                
throw new Exception("No type converter available for type: " + property.PropertyType);
            }

        }

    }

    
if (ex != null)
        
throw ex;

}

下面进入正题。看看在Webform下面的实现,思路还是一样的。先把我的实现代码贴上来再说
///   <summary>
///  根据对象自动给相应控件取值或者赋值
///   </summary>
public   class  ValuePicker
{
    
///   <summary>
    
///  把对象赋值给相应控件
    
///   </summary>
    
///   <param name="dataEntity"> 对象 </param>
    
///   <param name="page"> 要搜索控件的Page或者Master里的ContentPlaceHolder </param>
    
///   <returns></returns>
     public   int  SetValue( object  dataEntity, Control page)
    {
        
return  OperateValue(dataEntity, page,  true );
    }
    
///   <summary>
    
///  把相应控件的属性值赋给对象的相应属性
    
///   </summary>
    
///   <param name="dataEntity"> 对象 </param>
    
///   <param name="page"> 要搜索控件的Page或者Master里的ContentPlaceHolder </param>
    
///   <returns></returns>
     public   int  GetValue( object  dataEntity, Control page)
    {
        
return  OperateValue(dataEntity, page,  false );
    }
    
///   <summary>
    
///  根据每个控件的类型,获取对应操作的属性名称
    
///   </summary>
    
///   <param name="typeName"> 控件类型 </param>
    
///   <returns></returns>
     private   string  GetPropertyTypeName( string  typeName)
    {
        
switch  (typeName)
        {
            
case   " TextBox " :
                
return   " Text " ;
            
case   " DropDownList " :
                
return   " SelectedValue " ;
            
case   " CheckBox " :
                
return   " Checked " ;
            
case   " HiddenField " :
                
return   " Value " ;
            
default :
                
return   " Text " ;
        }
    }
    
///   <summary>
    
///  具体实现赋值和取值的方法
    
///   </summary>
    
///   <param name="dataEntity"> 对象 </param>
    
///   <param name="page"> 要搜索控件的Page或者Master里的ContentPlaceHolder </param>
    
///   <param name="isSetting"> 是否是要设置控件的值 </param>
    
///   <returns></returns>
     private   int  OperateValue( object  dataEntity, Control page,  bool  isSetting)
    {
        
try
        {
            Type EntityType 
=  dataEntity.GetType();
            Type ControlType;
            
// 取得所有的属性
            PropertyInfo[] Pinfos  =  EntityType.GetProperties(); ;
            Control Ctrl;
            Object Data 
=   null ;
            
string  PropertyTypeName;
            
// 遍历所有的属性
             foreach  (PropertyInfo Pinfo  in  Pinfos)
            {
                
// 查找属性对应的控件
                Ctrl  =  page.FindControl(Pinfo.Name);
                
if  (Ctrl  !=   null )
                {
                    ControlType 
=  Ctrl.GetType();
                    
// 取得控件存储值的属性
                    PropertyTypeName  =  GetPropertyTypeName(ControlType.Name);

                    
if  (isSetting  ==   true )
                    {
// 把对象的值设置给控件
                        Data  =  EntityType.InvokeMember(Pinfo.Name,
                         BindingFlags.GetProperty, 
null , dataEntity,  null );
                        Data 
=  ReDefineData(ControlType, Data, PropertyTypeName);
                        
object [] SettingData  =  { Data };
                        ControlType.InvokeMember(PropertyTypeName,
                       BindingFlags.SetProperty, 
null , Ctrl, SettingData);
                    }
                    
else
                    {
// 取得控件的值赋给对象对应的属性
                        Data  =  ControlType.InvokeMember(PropertyTypeName,
                        BindingFlags.GetProperty, 
null , Ctrl,  null );
                        Data 
=  ReDefineData(EntityType, Data, Pinfo.Name);

                        
object [] SettingData  =  { Data };
                        EntityType.InvokeMember(Pinfo.Name,
                        BindingFlags.SetProperty, 
null , dataEntity, SettingData);
                    }
                }
            }
            
return   0 ;
        }
        
catch  (System.Exception E)
        {
            System.Diagnostics.Debug.WriteLine(E.ToString());
            
// 注意
             throw  (E);
            
return   - 1 ;
        }
    }

    
///   <summary>
    
///  进行数据类型转换
    
///   </summary>
    
///   <param name="controlType"></param>
    
///   <param name="data"></param>
    
///   <param name="PropertyTypeName"></param>
    
///   <returns></returns>
     private   object  ReDefineData(Type controlType, Object data,  string  PropertyTypeName)
    {
        
if  (data  ==   null )
            
return   null ;
        
switch  (controlType.GetProperty(PropertyTypeName).PropertyType.Name)
        {
            
case   " Boolean " :
                
if  (( int )data  ==   1 )
                    data 
=   true ;
                
else
                    data 
=   false ;
                
break ;

            
case   " String " :
                data 
=  data.ToString();
                
break ;
            
case   " Int32 " :
                data 
=  Convert.ToInt32(data);
                
break ;
            
case   " Double " :
                data 
=  Convert.ToDouble(data);
                
break ;
            
default :
                
break ;
        }
        
return  data;
    }
}
在GetPropertyTypeName里面的类型还不够多。比如如果你用到了RadioButtonList,你可以自己加上对应的属性SelectedValue,在这里就只列这么多了。你可以自己改成更好的实现方法。另外ReDefineData应该也要相应的添加一些对应关现。在看了UpdateFrom的实现以后,其实这个类异常的处理应该要改成UpdateFrom才更好,这里就不改了,有空的话我会再改进一下。
另外你还可以写一个类以方便调用
/// <summary>
/// 提供页面操作的常用函数
/// </summary> 

public   class  PageUtility
{
    
/// <summary>
    
/// 设置当前页面上的控件值
    
/// </summary>
    
/// <param name="dataEntity">源数据</param>
    
/// <returns></returns>

    public static int SetPageValueForM(object dataEntity)
    
{
        ValuePicker Vp 
= new ValuePicker();
        Control ctl 
= CurPage.Master.FindControl("ContentPlaceHolder2");
        
return Vp.SetValue(dataEntity, ctl);
    }


    
/// <summary>
    
/// 把当前页面的值读取到控件
    
/// </summary>
    
/// <param name="dataEntity">取值的对象</param>
    
/// <returns></returns>

    public static int GetPageValueForM(object dataEntity)
    
{
        ValuePicker Vp 
= new ValuePicker();
        Control ctl 
= CurPage.Master.FindControl("ContentPlaceHolder2");
        
return Vp.GetValue(dataEntity, ctl);
    }


    
/// <summary>
    
/// 把当前页面的值读取到控件
    
/// </summary>
    
/// <param name="dataEntity">取值的对象</param>
    
/// <returns></returns>

    public static int GetPageValue(object dataEntity)
    
{
        ValuePicker Vp 
= new ValuePicker();
        
return Vp.GetValue(dataEntity, CurPage);
    }


    
/// <summary>
    
/// 设置当前页面上的控件值
    
/// </summary>
    
/// <param name="dataEntity">源数据</param>
    
/// <returns></returns>

    public static int SetPageValue(object dataEntity)
    
{
        ValuePicker Vp 
= new ValuePicker();
        
return Vp.SetValue(dataEntity, CurPage);
    }



    
/// <summary>
    
/// 返回当前页面类
    
/// </summary>

    public static Page CurPage
    
{
        
get return System.Web.HttpContext.Current.Handler as Page; }
    }

}
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值