如何使用 属性 名称和前缀从 属性 方面调用特定方法?
How call a specific method from property aspect with property name and prefix?
我想用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() 只允许一个固定的方法名。
什么是最好的方法?
当您需要导入一个没有固定预定义名称的方法时,您可以在方面实现 IAdviceProvider
接口并提供 ImportMethodAdviceInstance
将方法名称作为字符串参数.
另一个重点是您的 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()
{
}
}
我想用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() 只允许一个固定的方法名。 什么是最好的方法?
当您需要导入一个没有固定预定义名称的方法时,您可以在方面实现 IAdviceProvider
接口并提供 ImportMethodAdviceInstance
将方法名称作为字符串参数.
另一个重点是您的 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()
{
}
}