您的位置:首页 > 产品设计 > UI/UE

EF & Model Validation & WinForm UI DataBinding

2011-01-22 21:50 627 查看
asp.net mvc上使用EF(实体框架)中的Model Validation与UI自动绑定感觉还可以
最近碰到要做c/s结构系统,winform并没有直接支持,自己尝试实现一个

第一步
根据winform ui control上验证方式和数据绑定方式
EF上entity object实现IDataErrorInfo接口就可以了
第二步
利用DataAnnotation完成entity object上验证接口
DataAnnotation是.net内置的验证框架(其他验证框架有Castle Validator ,EntLib Validation Library)
使用DataAnnotation主要是为了减少第3方引用不方便,而且EF声明式验证需要结合MetaDataType关联验证类
.net内置的DataAnnotation中也有了

第三步
结合IDataErrorInfo和验证接口就可以达到的Model Validation与UI自动绑定的效果

第四步
EF设计器上自定义代码产生,他是利用T4来编写的,这样不用为每个entity object手动写patial类

系统最后采用的是EF+CAB(Composite UI Application Block)

因为采用Model Validation与UI自动绑定所以CAB这个框架下业务模块当然采用了MVC模式方式

验证部分实现代码如下:

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using System.Data.Objects.DataClasses;

namespace ChildrenModel
{
class EntityObjectValidationProvider : IValidationProvider
{
private PropertyInfo[] properties;
private object objectInstance;
private Dictionary<PropertyInfo, string> failedProperties = new Dictionary<PropertyInfo, string>();
public EntityObjectValidationProvider(object objectInstance)
{
this.objectInstance = objectInstance;
}
#region IValidationProvider Members

public virtual bool IsValid()
{

Type thisClass = objectInstance.GetType();
Type metaType = typeof(MetadataTypeAttribute);
bool isDefined = Attribute.IsDefined(thisClass, metaType);
if (!isDefined)
{
return true;
}
Attribute attribute = Attribute.GetCustomAttribute(thisClass, metaType);
MetadataTypeAttribute metaAttribute = attribute as MetadataTypeAttribute;
if (metaAttribute == null)
{
return true;
}

Type metaModelType = metaAttribute.MetadataClassType;

properties = GetProperties(metaModelType);
if (properties != null)
{
foreach (var prop in properties)
{

object[] objs = prop.GetCustomAttributes(typeof(ValidationAttribute), true);
foreach (var attrib in objs)
{
ValidationAttribute vAttrib = attrib as ValidationAttribute;
if (vAttrib!=null)
{

object[] runWhenObjs =prop.GetCustomAttributes(typeof(RunWhenAttribute), true);

RunWhen runWhen = RunWhen.Everytime;
foreach (var runWhenAttrib in runWhenObjs)
{
RunWhenAttribute rAttrib = runWhenAttrib as RunWhenAttribute;
if(rAttrib!=null)
{
runWhen = runWhen & rAttrib.RunWhen;
}
}
if (runWhen != 0)
{

Type modelType = objectInstance.GetType();
PropertyInfo modelPropInfo = modelType.GetProperty(prop.Name);
if (!vAttrib.IsValid(modelPropInfo.GetValue(objectInstance, null)))
{

failedProperties[modelPropInfo] = vAttrib.ErrorMessage;
return false;
}
else
{
failedProperties[modelPropInfo] = string.Empty;
}
if (prop.GetType() == typeof(EntityObject))
{
IValidationProvider ivp = Activator.CreateInstance(prop.GetType()) as IValidationProvider;
ivp.IsValid();

}
}

}

}
}
}
return true;

}

public virtual String[] ValidationErrorMessages
{
get
{

return failedProperties.Values.ToArray();
}
}

public virtual IDictionary PropertiesValidationErrorMessages
{
get { return failedProperties; }
}

#endregion
private PropertyInfo[] GetProperties(Type type)
{
if (properties == null || properties.Length == 0)
properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);

return properties;
}
}
}

最后T4产生的实体类效果的部分代码:

/// <summary>
/// No Metadata Documentation available.
/// </summary>
[EdmEntityTypeAttribute(NamespaceName="ChildrenModel", Name="Customer")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class Customer : EntityObject ,IValidationProvider, IDataErrorInfo
{
#region IDataErrorInfo Members
string IDataErrorInfo.Error
{
get
{
StringBuilder errors=new System.Text.StringBuilder();
foreach (string str in ValidationProvider.ValidationErrorMessages)
{
errors.Append(str);
}
return errors.ToString();
}
}

string IDataErrorInfo.this[string column]
{
get
{
Type t = this.GetType();
PropertyInfo info = t.GetProperty(column);
string errorMessage = string.Empty;
if (info != null)
errorMessage = ValidationProvider.PropertiesValidationErrorMessages[t.GetProperty(column)] as string;
if (errorMessage == null)
errorMessage = string.Empty;
return errorMessage;
}
}
#endregion
private IValidationProvider validationProvider;
IValidationProvider ValidationProvider
{
get
{
if (validationProvider == null)
validationProvider = new EntityObjectValidationProvider(this);

return validationProvider;

}
}
#region IValidationProvider Members

/// <summary>
/// Performs the fields validation. Returns true if no
/// validation error was found.
/// </summary>
/// <returns></returns>
/// <remarks>Forwards the call to <see cref="ActualValidator"/>.</remarks>
public virtual bool IsValid()
{
return ValidationProvider.IsValid();
}

public virtual String[] ValidationErrorMessages
{
get { return ValidationProvider.ValidationErrorMessages; }
}

public virtual IDictionary PropertiesValidationErrorMessages
{
get { return ValidationProvider.PropertiesValidationErrorMessages; }
}

#endregion
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: