使用 Type 变量进行转换,以便使用流畅的验证和后锐方面



我从这里了解到,不能用类型变量进行强制转换。

我在项目中使用流畅的验证进行实体验证,为此我使用 postsharp 编写了一个方面。但我被困在某个地方。在我的方面类的构造函数方法中,我得到了验证类的类型。在 Entry 方法中,我动态创建此类的示例并强制转换为 IValidator。但是由于我强制转换为 IValidator,因此无法将规则集参数传递给验证方法。我需要施放IValidator.这也是不可能的。我应该如何解决这个问题?我希望我能说出来。我为示例添加下面的代码.谢谢。

[PSerializable]
public class FluentValidationAspect : OnMethodBoundaryAspect
{
private readonly Type _validatorType;
private readonly string _ruleSet;
public FluentValidationAspect(Type validatorType, string ruleSet = null)
{
_validatorType = validatorType;
_ruleSet = ruleSet;
}
public override void OnEntry(MethodExecutionArgs args)
{
var entityType = _validatorType.BaseType?.GetGenericArguments()[0];
var entities = args.Arguments.Where(x => x.GetType() == entityType);

if (string.IsNullOrEmpty(_ruleSet))
{
var validator = (IValidator)Activator.CreateInstance(_validatorType);
foreach (var entity in entities)
ValidatorTool.FluentValidate(validator, entity);
}
else
{
var validator = (IValidator<entityType>)Activator.CreateInstance(_validatorType);
foreach (var entity in entities)
ValidatorTool.FluentValidate<entityType>(validator, entity);
}
}
}
public static class ValidatorTool
{
public static void FluentValidate(IValidator validator, object entity)
{
var result = validator.Validate(entity);
if (result.Errors.Any())
throw new ValidationException(result.Errors);
}
public static void FluentValidate<T>(IValidator<T> validator, T entity, string ruleSet) where T : class, new()
{
var result = validator.Validate(entity, ruleSet: ruleSet);
if (result.Errors.Any())
throw new ValidationException(result.Errors);
}
}

您有两个选择。可以使用反射来调用泛型方法的正确实例FluentValidate或者需要方面本身是泛型类型。

后一个选项在运行时会更快。下面的代码使用以编程方式向目标方法添加泛型方面的IAspectProvider。提供程序类型不必是一个方面(但可以(。提供的泛型方面不能派生自常规类型,因为属性类型不能是泛型的,因此它实现了方面接口。

[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
[MulticastAttributeUsage(MulticastTargets.Method)]
public class FluentValidationAspect : MulticastAttribute, IAspectProvider
{
private readonly Type _validatorType;
private readonly string _ruleSet;
public FluentValidationAspect(Type validatorType, string ruleSet = null)
{
_validatorType = validatorType;
_ruleSet = ruleSet;
} 
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
var entityType = _validatorType.BaseType?.GetGenericArguments()[0];
var genericAspectType = typeof(FluentValidationAspect<>).MakeGenericType(entityType);
yield return new AspectInstance(targetElement, new ObjectConstruction(genericAspectType, new object[] { _validatorType, _ruleSet }));
}
}
[PSerializable]
public class FluentValidationAspect<T> : IMethodLevelAspect
{
private Type _validatorType;
private string _ruleSet;
public FluentValidationAspect(Type validatorType, string ruleSet = null)
{
_validatorType = validatorType;
_ruleSet = ruleSet;
}
public void RuntimeInitialize(MethodBase method)
{
}
[SelfPointcut]
[OnMethodEntryAdvice]
public void OnEntry(MethodExecutionArgs args)
{
var entities = args.Arguments.Where(x => x is T).Select(x => (T)x);
var validator = (IValidator<T>)Activator.CreateInstance(_validatorType);
foreach (var entity in entities)
ValidatorTool.FluentValidate(validator, entity);
}
}

请注意,运行时不涉及反射。但是,我会考虑从OnEntry建议中完全删除 LINQ 以获得更好的性能。

这解决了我的问题,我相信有人会再次为此而来

public static void Validate(IValidator validator, object entity)
{
var context = new ValidationContext<object>(entity);
var result = validator.Validate(context);
if (result.Errors.Count > 0)
{
throw new ValidationException(result.Errors);
}
}

最新更新