我想用possharp开发一个NotifyDataErrorInfoAspect。
值的验证取决于几个可变属性(MinValue,MaxValue ...)。合同不能使用可变参数。
我想构建类似于DependencyPropertyAspect的东西。 具有[DependencyProperty]的每个属性都有许多可选方法。例如ValidatePropertyName。
[DependencyProperty]
public string Email { get; set; }
private bool ValidateEmail(string value)
{
return EmailRegex.IsMatch(value);
}
我该怎么做?
[NotifyDataErrorInfo]
public string Name{ get; set; }
private IList<DataErrorInfo> ValidateName(string value)
{
return this.IsValidName(value);
}
[NotifyDataErrorInfo]
public int Age{ get; set; }
private IList<DataErrorInfo> ValidateAge(int value)
{
return this.IsValidAge(value);
}
[NotifyDataErrorInfo]
public string Email { get; set; }
private IList<DataErrorInfo> ValidateEmail(string value)
{
return this.IsValidEmail(value);
}
属性ImportMethod()仅允许使用固定的方法名称。 最好的方法是什么?
答案 0 :(得分:1)
当需要导入没有固定预定义名称的方法时,可以在方面实现IAdviceProvider
接口,并提供将方法名称作为字符串参数的ImportMethodAdviceInstance
。 / p>
另一个重要的一点是,您的Validate方法采用特定类型的参数,而不是object
。当前,无法在C#中创建一般属性,因此您需要创建两个方面类来处理这种情况:作为方面提供者的属性和一般方面的实现。
以下是NotifyDataErrorInfo方面的示例实现:
[PSerializable]
public class NotifyDataErrorInfoAttribute : LocationLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
Type propertyType = ((LocationInfo)targetElement).LocationType;
Type aspectType = typeof(NotifyDataErrorInfoAspectImpl<>).MakeGenericType(propertyType);
yield return new AspectInstance(
targetElement, (IAspect) Activator.CreateInstance(aspectType));
}
}
[PSerializable]
public class NotifyDataErrorInfoAspectImpl<T> : ILocationInterceptionAspect,
IInstanceScopedAspect,
IAdviceProvider
{
public Func<T, IList<DataErrorInfo>> ValidateDelegate;
public IEnumerable<AdviceInstance> ProvideAdvices(object targetElement)
{
LocationInfo property = (LocationInfo)targetElement;
string validateMethodName = "Validate" + property.Name;
yield return new ImportMethodAdviceInstance(
typeof(NotifyDataErrorInfoAspectImpl<>).GetField("ValidateDelegate"),
validateMethodName,
true);
}
public void OnSetValue(LocationInterceptionArgs args)
{
if (ValidateDelegate((T) args.Value)?.Any() == true)
throw new ArgumentException("...");
args.ProceedSetValue();
}
public void OnGetValue(LocationInterceptionArgs args)
{
args.ProceedGetValue();
}
public void RuntimeInitialize(LocationInfo locationInfo)
{
}
public object CreateInstance(AdviceArgs adviceArgs)
{
return this.MemberwiseClone();
}
public void RuntimeInitializeInstance()
{
}
}