1

我有一个带有客户端/服务器架构的小框架我在我的业务层中使用这个工具:

DI = SimpleInjector

DynamicProxy 拦截 = Castle.Core

现在我需要验证一些验证!例如看这个方法:

public void DeleteFakeItem (Guid userId, Guid fakeItemId)
{
    userAccountService.IsAuthorized(userId, FeatureIndex.DeleteFakeItem);

    if (fakeItemId == Guid.EmptyGuid || userId == Guid.EmptyGuid) 
        throw new ArgumentNullException("parameters are not correct!");

    if (!repo.IsFakeItemIsDeletable(fakeItemId))
        throw new Exception("you can not delete this item!");

    var fakeItem = repo.GetFakeItem(fakeItemId);

    if (fakeItem == null)
        throw new Exception("this fakeItem dose not exists!");

    repo.DeleteActivityCenter(fakeItem);
}

但是,我有很多方法,我的方法彼此非常不同,那么解决方案在哪里?因为我无法为我的方法创建一个好的抽象。

如何实现横切功能来验证我的参数?

我想我可以使用拦截器和属性来做到这一点,例如[Validate(ValidateEnum.NotNull)]每个参数的属性。

什么是正确的方法?

我的实体的第二个问题:我能否获得流畅的 API 验证规则,以使用带有拦截器的反射来验证实体?

例如我想获取规则,如果有IsRequired()规则,验证为不为空。

我不想使用装饰器模式,因为它让我重构了很多;

4

2 回答 2

1

我只是通过将反射与通用接口相结合来解决我的问题,所以我唯一需要的是为每个实体实现通用接口。

我有一个拦截所有方法的拦截器。它对我有用。但谁能给我一些关于表演的信息?这是进行验证的正确方法吗?拦截器:

public class ValidatorInterceptor : IInterceptor
{

    private readonly IServiceFactory factory;

    public ValidatorInterceptor(IServiceFactory _factory)
    {
        factory = _factory;
    }

    public void Intercept(IInvocation invocation)
    {
        var methodParameterSet = invocation.InvocationTarget.GetType().GetMethod(invocation.Method.Name).GetParameters().ToList();
        for (var index = 0; index < methodParameterSet.Count; index++)
        {
            var parameter = methodParameterSet[index];
            var paramType = parameter.ParameterType;
            var customAttributes = new List<object>();
            var factoryMethod = factory.GetType().GetMethod("GetService");
            var baseValidatorType = typeof(IValidator<>);
            var validatorType = baseValidatorType.MakeGenericType(paramType);
            factoryMethod = factoryMethod.MakeGenericMethod(validatorType);
            var validator = factoryMethod.Invoke(factory, null);

            customAttributes.AddRange(parameter.GetCustomAttributes(true).Where(item => item.GetType().Name.StartsWith("Validate")));
            foreach (var attr in customAttributes)
            {
                dynamic attribute = attr;
                var method = validator.GetType().GetMethod("Validate");
                method = method.MakeGenericMethod(paramType);
                object[] parameterSet = {invocation.Arguments[index], attribute.Rule, attribute.IsNullCheck};
                method.Invoke(validator, parameterSet);
            }
        }

        invocation.Proceed();
    }
}

UserAccount Entity 的 IValidator 的实现是这样的:

public class ValidateUserAccount<T> : IValidator<T> where T : UserAccount
{
    public void Validate<T>(T entity, object obj1 = null, object obj2 = null) where T : class
    {
        var item = (UserAccount) Convert.ChangeType(entity, typeof(UserAccount));

        if (item == null)
            throw new ArgumentNullException("user account cant be null");
    }

}

对于字符串验证器:

public class ValidateString : IValidator<string>
{
    public void Validate<T>(T entity, object rukeObj = null, object nullChekcObj = null) where T : class
    {
        var item = (string) Convert.ChangeType(entity, typeof(string));
        var rule = (Regex)Convert.ChangeType(rukeObj, typeof(Regex));
        var reqItem = Convert.ChangeType(nullChekcObj, typeof(bool));
        var isRequire = reqItem != null && (bool) reqItem;

        if (isRequire && string.IsNullOrEmpty(item))
            throw new ArgumentException("value can not be null!");

        if (!rule.Match(item).Success)
            throw new ArgumentException("[" + item + "] is not a valid input!");

    }
}
于 2017-09-09T13:39:07.707 回答
0

我对这个问题的解决方案如下(你可以在这里找到):

  1. 接口和实现类,以便能够更改验证逻辑 - 验证逻辑可能存在错误或更改。
  2. 使用全局异常处理程序使大多数方法无效并引发异常。
  3. 将不同程序集中的实现和接口分开。通过这种方式,我获得了单元测试的性能优势。我为消息服务、缓存服务、持久性服务提供了单独的程序集,因为它们的实现非常庞大并且有很多依赖项,这些依赖项会减慢单元测试的运行速度。当您的单元测试仅引用接口程序集时,测试的编译和运行速度会更快。这一点对巨大而长期的项目有非常非常大的影响。- 这会影响代码库的质量!
于 2017-08-22T07:34:10.367 回答