1

I have a small framework with Client/Server Architecture I use this Tools in my Business Layer:

DI = SimpleInjector

DynamicProxy For Interception = Castle.Core

now i need to validate some validations! for example look at this method:

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);
}

but, i have a lot of methods, my methods are very different to each other, so where is the solution? because i can not create a good abstraction for my methods.

how can i implement a cross cutting feature to validate my parameters?

i think i can do it using interceptor and attributes, for example an attribute like [Validate(ValidateEnum.NotNull)] for each parameter.

what is the correct way?

and second question for my entities: can i get the fluent API validation Rules to validate entities based on them using reflection with a interceptor?

for example i wanna get rules, if there is a IsRequired() rule, validate as not null.

i don't wanna use decorator pattern because it's makes me refactoring a lot;

mohammadreza
  • 158
  • 12
  • This is a very, very broad question, which might be unsuited for Stackoverflow. Also, although it might cause you to refactor a lot, to me the solution to your problems is to apply [this pattern](https://cuttingedge.it/blogs/steven/pivot/entry.php?id=91). – Steven Aug 21 '17 at 12:08
  • @Steven oh God, Are you serious? the command pattern? i hate it, i must to write a lot of codes with this pattern :( | tnx for comment at all. seeking a solution for a lazy developer – mohammadreza Aug 21 '17 at 12:38
  • So you want to improve your design, but don't want to refactor it? Good luck with that :). btw, you might have misread that article. The article does _not_ describe the Command pattern, but a completely different pattern that whether you like it or not, does solve all the problems you described in your question (and much more). – Steven Aug 21 '17 at 13:25

2 Answers2

1

I just solve my problem with combine reflection with generic interfaces, so the only thing I need is to implement the generic interface for every entity.

I have an interceptor that intercepts all methods. and its works for me. but can anyone give me some information about the performance? is it a correct way to do validation? interceptor:

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

and the implementation of IValidator for UserAccount Entity is like this:

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");
    }

}

and for string validator:

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!");

    }
}
mohammadreza
  • 158
  • 12
0

My solution to the problem is the following (you can find it here) :

  1. Interface and implementation class in order to be able to change the validation logic - there maybe bugs or change in validation logic.
  2. Make most of the methods void and throw exceptions with a global exception handler.
  3. Separate the implementation and interface in different assemblies. By this I gain performance benefit for the unit tests. I have separate assemblies for Messaging service, Caching services, Persistence services because their implementations are huge and have lots of dependencies which slow unit test runs to oblivion. When your unit tests reference only the interface assemblies the tests compile and run a lot faster. This point has very very big impact on huge and long lived projects. - this affects quality of the codebase!
Ognyan Dimitrov
  • 6,026
  • 1
  • 48
  • 70
  • tnx for your replying, it's good at all, but you need to inject this service to all your services | I have a better idea, extend it to validate Types, and you use a DI, you can decorate your services with your validator or implement an interceptor. – mohammadreza Aug 22 '17 at 09:09