如何使用 属性 名称和前缀从 属性 方面调用特定方法?

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()
    {
    }
}