2009-07-24 8 views
0

私はこのGeneric DuplicateValidationRuleの動作を試しています。これは、基本的に(渡された汎用ビジネスオブジェクト型に基づいて)重複をチェックします。例えばIBankAccountビジネスオブジェクトを取ることができます:一般的なDuplicateValidationRule(重複しているビジネスオブジェクトのチェック)

T =てBusinessObjectタイプクラス(人、住所、銀行口座の、:

public interface IBankAccount : IMyBusinessObjectBase 
{ 
    IBank Bank 
    { 
     get; 
     set; 
    } 

    IBankAccountType BankAccountType 
    { 
     get; 
     set; 
    } 

    string AccountName 
    { 
     get; 
     set; 
    } 

    string AccountNumber 
    { 
     get; 
     set; 
    } 

    DateTime EffectiveDate 
    { 
     get; 
     set; 
    } 
} 

は、私がIBankAccount

次のコレクション
IBankAccount acc1 = new BankAccount(); 
acc1.AccountName = "Account1"; 
acc1.AccountNumber = "123456"; 
acc1.Bank = FetchBusinessObjectByID(1); //Fetch Bank 1 

IBankAccount acc2 = new BankAccount(); 
acc2.AccountName = "Account2"; 
acc2.AccountNumber = "654321"; 
acc2.Bank = FetchBusinessObjectByID(1); //Fetch Bank 1 

IBankAccount acc3 = new BankAccount(); 
acc3.AccountName = "Account3"; 
acc3.AccountNumber = "123456"; 
acc3.Bank = FetchBusinessObjectByID(2); //Fetch Bank 2 

IBankAccount acc4 = new BankAccount(); 
acc4.AccountName = "Account3"; 
acc4.AccountNumber = "123456"; 
acc4.Bank = FetchBusinessObjectByID(1); //Fetch Bank 2 

ICollection<IBankAccount> bankAccounts = new List<IBankAccount>(); 
bankAccount.Add(acc1); 
bankAccount.Add(acc2); 
bankAccount.Add(acc2); 
bankAccount.Add(acc4); 

パラメータを持っているとしましょうBank、BankBranchなど)string [] entityPropertyName =重複をチェックするときに含めるプロパティの配列。

次に、以下のシナリオを使用してください。アカウント番号と銀行を確認して、重複した銀行口座を確認したいとします。口座番号は銀行内で一意ですが、別の銀行にも存在する可能性があります。したがって、上記のリストを見ると、Acc1、Acc2、Acc3が有効です。その銀行の口座番号が既に存在するため、Acc4は無効です。

したがって、validateの呼び出しは次のようになります。

DuplicateValidationRule.Validate(newBankAccountEntry、new string [] {"AccountNumber"、 "Bank.Name"});

上記のコードは、重複をチェックするビジネスエンティティと、チェックするプロパティを含むプロパティ配列を渡します。

public ValidationError Validate<T>(T entityProperty, string[] entityPropertyName) 
    {   
     ICollection<T> businessObjectList = FetchObjectsByType<T>(); 

     bool res = true; 
     for (int i = 0; i < entityPropertyName.Length; i++) 
     { 
      object value = getPropertyValue(entityProperty, entityPropertyName[i]); 

//By Using reflection and the getPropertyValue method I can substitute the properties to //compare. 
      if (businessObjectList.Any(x => getPropertyValue(x, entityPropertyName[i]).Equals(value) && 
             x.GetType().GetProperty("ID").GetValue(x,null).ToString()           
             != ((IBusinessObjectBase)entityProperty).ID.ToString())) 
       res &= true; 
      else 
       res &= false;    
     } 

     if (res) 
      return new ValidationError(_DuplicateMessage); 
     else 
      return ValidationError.Empty; 
    } 

この方法は、上の重複をチェックするために実際のオブジェクトを取得するために使用されます。

private static object getPropertyValue(object obj, string propertyName) 
    { 
     string[] PropertyNames = propertyName.Split('.'); 

     object propertyValue = obj; 

     for (int i = 0; i < PropertyNames.Length; i++) 
     { 
      propertyValue = propertyValue.GetType().GetProperty(PropertyNames[i], BindingFlags.Public | 
        BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy). 
        GetValue(propertyValue, null); 
     } 

     if (propertyValue.GetType() == typeof(string)) 
      return propertyValue.ToString().ToLower(CultureInfo.CurrentCulture); 
     else 
      return propertyValue; 
    } 

上記のコードの作品を​​、それが欠陥を持っている:あなたがチェックしている場合、上記のコードのみ動作します

DuplicateValidationRule.Validate<IBankAccount>(newBankAccountEntry,new string[] {"AccountNumber"}); 

あなたは、たとえば、に対してチェックするために、別のプロパティを追加します:

012重複した試合のための単一のプロパティ

このコードでは、リスト内の次のoccurangeの2番目のプロパティがチェックされます。比較対象の現在のオブジェクトの.Anyのすべてのプロパティをテストする必要があります。これがうまくいくことを願って、誰かが私にこれを解決するためのアドバイスをくれますか?ありがとう:)

答えて

1

をここで私はあなたがてBusinessObjectエンティティを持っていては、BusinessObjectsのリスト内の別のに対して、すべてのプロパティを一致させたいという仮定の下にあります:あなたは、おそらくある場合

public ValidationError Validate<T>(T entityProperty, string[] entityPropertyName) 
{     
    ICollection<T> businessObjectList = FetchObjectsByType<T>(); 
    Hashtable properties = EnumeratePropertyInfo<T>(entityProperty, entityPropertyName); 
    return businessObjectList.Any(obj => IsDuplicate<T>(obj, properties)) == true ? new ValidationError(_DuplicateMessage) : ValidationError.Empty; 
} 


private Hashtable EnumeratePropertyInfo<T>(T entityProperty, string[] entityPropertyName) 
{ 
    Hashtable properties = new Hashtable(); 
    for (int i = 0; i < entityPropertyName.Length; i++)   
    {    
     object value = getPropertyValue(entityProperty, entityPropertyName[i]); 
     properties.Add(entityPropertyName[i], value); 
    } 
    return properties; 
} 

// all properties must be matched for a duplicate to be found 
private bool IsDuplicate<T>(T entityProperty, Hashtable properties) 
{ 
    foreach(DictionaryEntry prop in properties) 
    { 
     var curValue = getPropertyValue(entityProperty, prop.Key.ToString()); 
     if (!prop.Value.Equals(curValue)) 
     { 
      return false; 
     } 
    } 
    return true; 
} 

プロパティマッピングにHastableを使用することに少し気をつけたら、代わりに独自のカスタムタイプを作成することをお勧めします。

希望に役立ちます。

+0

あなたのコードがうまくいくかのように見えます。私の現在の解決策を投稿させてください。うまくいけば、使用する方が良いと思われるユーザー入力があります。どうもありがとう!! – FaNIX

1

私が今間違っていない場合、あなたはそれらの組み合わせではなくすべての単一のプロパティのユニークな存在をチェックしています。あなたがインターフェイスで定義されたMyComparableMethodメソッドを使用することができます任意の方法に比べて

public interface IMyComparable<T> 
{ 
    bool MyComparableMethod(T account); 
} 

public interface IBankAccount : IMyBusinessObjectBase, IMyComparable<T> 
{ 
... 
    public bool MyComparableMethod(IBankAccount account) 
    { 
     return this.AccountNumber == account.AccountNumber && 
       this.Bank.Name == account.Bank.Name && 
       this.Id != account.Id; 
    } 
} 

public ValidationError Validate<T>(T entityProperty) where T : IMyComparable<T> 
{ 
... 
    if (!businessObjectList.Any(x => entityProperty.MyComparableMethod(x)) 
     return new ValidationError(_DuplicateMessage); 
... 

代わりの反射を利用して、あなたは、このように(。例えばIMyComparable)Equalsメソッドやインタフェースを使用することはできません。

・ホープ、このことができます:)

+0

私はあなたが何をしようとしているのか分かりません。あなたは現時点で私の問題であるそれらの組み合わせではなく、すべての単一の財産のユニークな存在をチェックしていると言っても間違いありません。あなたが言っていることの完全な例を提供してください。 は、それがIMyComparableはこのようなものになりますので、任意のビジネス・オブジェクト・タイプに取るようにseensことを忘れないでください:IMyComparable { ブールMyComparableMethod(Tエンティティ) パブリックインターフェイスを。 } – FaNIX

+0

私の比較方法は完璧ではありませんが(例えばnullをチェックしません)、コードは私の考えを表現していると思います – marcob

0

問題への私の解決策。 getPropertyValueへの変更はありません。入力してください。おかげ

public ValidationError Validate<T>(T entityProperty, string[] entityPropertyName) 
{ 
    ICollection<T> businessObjectList = 
     BusinessContextManagerService.Fetch<ICollection<T>>(Criteria.ActiveAndDormant); 

    bool res = true; 
    object entityPropertyValue = null; 

    // Only Checking one property 
    if (entityPropertyName.Length == 1) 
    { 
     entityPropertyValue = getPropertyValue(entityProperty, entityPropertyName[0]); 

     if (businessObjectList.Any(x => getPropertyValue(x, entityPropertyName[0]).Equals(entityPropertyValue) && 
            x.GetType().GetProperty("ID").GetValue(x, null).ToString() 
            != ((IBusinessObjectBase)entityProperty).ID.ToString())) 
      res &= true; 
     else 
      res &= false; 
    } 
    else 
    { 
     foreach (object obj in businessObjectList) 
     { 
      res = true; 
      int objID = (Int32)obj.GetType().GetProperty("ID").GetValue(obj, null); 

      for (int i = 0; i < entityPropertyName.Length; i++) 
      { 
       entityPropertyValue = getPropertyValue(entityProperty, entityPropertyName[i]); 
       object objValue = getPropertyValue(obj, entityPropertyName[i]); 

       if (objValue.Equals(entityPropertyValue) && objID != ((IBusinessObjectBase)entityProperty).ID) 
        res &= true; 
       else 
        res &= false; 

       if (res == false) 
        break; 
      } 

      if (res == true) 
       break; 
     } 
    } 

    if (res) 
     return new ValidationError(_DuplicateMessage); 
    else 
     return ValidationError.Empty; 
} 
+0

あなたの解決策は疑いの余地はありませんが、読みやすさのために少し混乱しています。また、そこにいくつかの重複したコードがあります。それを少しリファクタリングして、ジェネリックメソッドに委譲しようとする必要があります。私のソリューションはこれをうまく行い、Validateメソッドを3行に減らします。 2セットのハッシュテーブルプロパティを渡し、.Equalsを使用してそれらを比較するだけで、重複したメソッドをさらに改善することもできます。後で更新する予定です。しかし、一日の終わりには、あなたがしたいことがあなたの決定です。 – James

0

私はタイムスパンであなたのコードをテストし、私と一緒に細かいです同じ時間を取るように見えます。あなたのコードはもっと良く見えますので、私はあなたの解決策に行くでしょう、私を助けるために時間をとってくれてありがとう、ありがとう。

PS:これを動作させるには、次のように変更する必要がありました。すべてのユニットテストは現在終了しています:)

private bool IsDuplicate<T>(T entityProperty, Hashtable properties) 
    { 
     bool res = true; 

     foreach (DictionaryEntry prop in properties) 
     { 
      var curValue = getPropertyValue(entityProperty, prop.Key.ToString()); 
      if (prop.Value.Equals(curValue)) 
      { 
       res &= true; 
      } 
      else 
       res &= false; 
     } 
     return res; 
    } 
+0

うれしい私は助けることができました! Btw私はちょうど気付いた、私のコードは実際にIsDuplicateメソッドの正しいです、私はちょうど追加することを忘れてしまった!演算子は "if(!prop.Value.Equals(curValue))"でなければなりません。 – James

+0

がフラグを持ち、それを常にtrue/falseに設定すると、それは一度falseになると、プロパティセットが等しくないことが分かります。だから、できるだけ早くループを飛ばしたいと思う。私はIsDuplicateMethodを更新しました – James

関連する問題