C# 使用类型变量强制转换以使用fluent验证和postsharp aspect
我从中了解到,不能使用类型变量进行转换 我在项目中使用fluent验证进行实体验证,为此,我使用postsharp编写了一个方面。但我被困在某个地方了。在aspect类的构造函数方法中,我得到了验证类的类型。在Entry方法中,我动态创建了该类的一个示例,并将其转换为IValidator。但由于我强制转换到IValidator,因此无法将规则集参数传递给Validate方法。我需要施展IValidator。这也是不可能的。我该如何处理这个问题?我希望我能告诉你。我为示例添加了下面的代码。谢谢C# 使用类型变量强制转换以使用fluent验证和postsharp aspect,c#,casting,fluentvalidation,postsharp,aspect,C#,Casting,Fluentvalidation,Postsharp,Aspect,我从中了解到,不能使用类型变量进行转换 我在项目中使用fluent验证进行实体验证,为此,我使用postsharp编写了一个方面。但我被困在某个地方了。在aspect类的构造函数方法中,我得到了验证类的类型。在Entry方法中,我动态创建了该类的一个示例,并将其转换为IValidator。但由于我强制转换到IValidator,因此无法将规则集参数传递给Validate方法。我需要施展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);
}
}
[可序列化]
公共类FluentValidationSpect:OnMethodBoundaryAspect
{
私有只读类型_validator类型;
私有只读字符串_规则集;
public FluentValidationSpect(类型validatorType,字符串规则集=null)
{
_validatorType=validatorType;
_规则集=规则集;
}
public override void OnEntry(MethodExecutionArgs args)
{
var entityType=_validatorType.BaseType?.GetGenericArguments()[0];
var entities=args.Arguments.Where(x=>x.GetType()==entityType);
if(string.IsNullOrEmpty(_规则集))
{
var validator=(IValidator)Activator.CreateInstance(_validatorType);
foreach(实体中的var实体)
FluentValidate(验证器、实体);
}
其他的
{
var validator=(IValidator)Activator.CreateInstance(_validatorType);
foreach(实体中的var实体)
FluentValidate(验证器、实体);
}
}
}
公共静态类验证工具
{
公共静态void FluentValidate(IValidator验证器,对象实体)
{
var结果=验证器。验证(实体);
if(result.Errors.Any())
抛出新的ValidationException(result.Errors);
}
publicstaticvoidfluentvalidate(IValidator验证器,T实体,字符串规则集),其中T:class,new()
{
var result=validator.Validate(实体,规则集:规则集);
if(result.Errors.Any())
抛出新的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);
}
}
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
[多播属性(多播目标。方法)]
公共类FluentValidationSpect:MulticastAttribute,IAspectProvider
{
私有只读类型_validator类型;
私有只读字符串_规则集;
public FluentValidationSpect(类型validatorType,字符串规则集=null)
{
_validatorType=validatorType;
_规则集=规则集;
}
公共IEnumerable ProvideSpects(对象targetElement)
{
var entityType=_validatorType.BaseType?.GetGenericArguments()[0];
var genericAspectType=typeof(FluentValidationSpect)。MakeGenericType(entityType);
返回新的AspectInstance(targetElement,新的ObjectConstruction(genericAspectType,新对象[]{U validatorType,URuleSet}));
}
}
[可序列化]
公共类FluentValidationSpect:IMethodLevelAspect
{
私有类型_校验类型;
私有字符串_规则集;
public FluentValidationSpect(类型validatorType,字符串规则集=null)
{
_validatorType=validatorType;
_规则集=规则集;
}
public void RuntimeInitialize(MethodBase方法)
{
}
[自切入点]
[关于方法建议]
public void OnEntry(MethodExecutionArgs args)
{
var entities=args.Arguments.Where(x=>x是T)。选择(x=>(T)x);
var validator=(IValidator)Activator.CreateInstance(_validatorType);
foreach(实体中的var实体)
FluentValidate(验证器、实体);
}
}
请注意,运行时不涉及反射。但是,我会考虑从代码< >条目>代码/建议中删除LINQ,以获得更好的性能。 < P>这是我的问题,有人会再次来此,我相信
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);
}
}
公共静态无效验证(IValidator验证程序,对象实体)
{
var context=新的ValidationContext(实体);
var result=validator.Validate(上下文);
如果(result.Errors.Count>0)
{
抛出新的ValidationException(result.Errors);
}
}