C# 使用类型变量强制转换以使用fluent验证和postsharp aspect

C# 使用类型变量强制转换以使用fluent验证和postsharp aspect,c#,casting,fluentvalidation,postsharp,aspect,C#,Casting,Fluentvalidation,Postsharp,Aspect,我从中了解到,不能使用类型变量进行转换 我在项目中使用fluent验证进行实体验证,为此,我使用postsharp编写了一个方面。但我被困在某个地方了。在aspect类的构造函数方法中,我得到了验证类的类型。在Entry方法中,我动态创建了该类的一个示例,并将其转换为IValidator。但由于我强制转换到IValidator,因此无法将规则集参数传递给Validate方法。我需要施展IValidator。这也是不可能的。我该如何处理这个问题?我希望我能告诉你。我为示例添加了下面的代码。谢谢 [

我从中了解到,不能使用类型变量进行转换

我在项目中使用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);
}
}