1

非常不同的方法,我有一個客戶機/服務器體系結構的小框架,我在業務層使用此工具:實現一個跨領域驗證使用C#

DI = SimpleInjector

DynamicProxy截取=城堡。核心

現在我需要驗證一些驗證!例如看看這個方法:

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()規則,驗證爲非空。

我不想使用裝飾模式,因爲它使我重構很多;

+0

這是一個非常,非常廣泛的問題,這可能不適合Stackoverflow。另外,雖然它可能會導致你重構很多,但對我來說,解決你的問題的方法是應用[此模式](https://cuttingedge.it/blogs/steven/pivot/entry.php?id=91)。 – Steven

+0

@Steven哦上帝,你認真嗎?命令模式?我討厭它,我必須用這種模式編寫大量的代碼:(| tnx以供評論。爲懶惰開發人員尋求解決方案 – mohammadreza

+0

所以你想改進你的設計,但不想重構它嗎?好與運氣:)。順便說一句,你可能誤解了那篇文章。文章並不描述命令模式,而是一種完全不同的模式,不管你是否喜歡,都能解決你在問題中描述的所有問題(以及更多)。 – Steven

回答

0

我只是解決了與通用接口結合反射的問題,所以我唯一需要的是爲每個實體實現通用接口。

我有攔截所有方法的攔截器。和它的作品。但任何人都可以給我一些關於表現的信息嗎?這是一種驗證的正確方法嗎? 攔截:

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

和IValidator爲UserAccount實體的實現是這樣的:

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

    } 
} 
0

我對這個問題的解決方案如下(you can find it here):

  1. 接口和實現類,以便能夠改變驗證邏輯 - 也許有錯誤或驗證邏輯變化。
  2. 使大多數方法無效並用全局異常處理程序拋出異常。
  3. 將實現和接口分開在不同的程序集中。通過這個,我獲得了單元測試的性能優勢。我有單獨的消息傳遞服務,緩存服務,持久性服務的程序集,因爲它們的實現非常龐大,並且具有很多依賴性,從而減慢了單元測試的運行速度。當你的單元測試只引用接口程序集時,測試的編譯和運行速度會更快。 這一點對巨大的和長期存在的項目有非常大的影響。 - 這會影響代碼庫的質量!
+0

tnx您的回覆,這是很好的,但你需要注入這項服務到您的所有服務|我有一個更好的主意,擴展它來驗證類型,並且你使用DI,你可以用你的驗證器裝飾你的服務或者實現一個攔截器。 – mohammadreza