1

小さなプロジェクト用の簡単な検証プロセスを作成しました。検証規則は、クラスのプロパティへの属性として作成されます。

クラス型を渡す必要がある静的クラスがあります。このメソッドは、指定されたクラスの一連のルールが既に辞書にあるかどうかを最初に確認します。そうでない場合は、リフレクションを使用して各プロパティを調べます。

この種のアプローチを使用する場合、何か問題はありますか? マルチスレッド環境でアクセスした場合に問題が発生する可能性があるのではないかと心配しています。

public static class Validator
{
    private static Dictionary<Type, ValidationRulesCollection> _validationRules = new Dictionary<Type, ValidationRulesCollection>();

    public static ValidationRulesCollection GetValidationRules(object obj)
    {
        return GetValidationRules(obj.GetType());
    }

    public static ValidationRulesCollection GetValidationRules(Type t)
    {
        ValidationRulesCollection rules = null;

        /* Check if the centralized rules repository already contains the rules for this class type */
        if (_validationRules.ContainsKey(t) == true)
        {
            rules = _validationRules[t];
        }
        else
        {
            /* Using reflection, get the list of properties for the class type */
            PropertyInfo[] properties = t.GetProperties();

            if (properties != null)
            {
                /* Iterate through each property info and check if it contains a validation rule */
                ValidationAttribute[] attribs = null;
                foreach (PropertyInfo property in properties)
                {
                    /* For each property, check if it contains a validation rule */
                    attribs = (ValidationAttribute[])property.GetCustomAttributes(typeof(ValidationAttribute), true);

                    if (attribs != null)
                    {
                        foreach (ValidationAttribute attrib in attribs)
                        {
                            if (rules == null)
                                rules = new ValidationRulesCollection();

                            /* Add the validation rule to the collection */
                            rules.Add(new ValidationRule(property, attrib));
                        }
                    }
                }
            }

            /* Add the rules collection to the centralized rules repository */
            if (rules.Count > 0)
                _validationRules.Add(t, rules);
            else
                throw new ArgumentNullException("The type " + t.ToString() + " does not have any ValidationAttributes");
        }

        return rules;
    }

    public static ValidationRulesCollection Validate(object obj)
    {
        /* Get the Validation Rules */
        ValidationRulesCollection rules = GetValidationRules(obj);

        /* Validate the rules */
        foreach (ValidationRule rule in rules)
        {
            rule.Validate(obj);
        }

        return rules;
    }
}
4

2 に答える 2

3

Dictionaryスレッドセーフではありません。そして、あなたの方法GetValidationRulesはそれを読み書きしています。複数のスレッドがこのメソッドを呼び出すと、辞書データが破損する可能性があります。これを回避するには、lock(...){ ... }すべての辞書メソッド呼び出しをカバーする a を配置します。

于 2013-03-29T18:17:52.990 に答える
3

これにより、マルチスレッド環境で問題が発生する可能性があります。通常、Dictionary<K,V>クラスはスレッドセーフではありません。データの破損や正確性の問題に加えて、まれに、あるスレッドが別のスレッドでサイズ変更中に辞書にヒットすると、スレッドがループに陥って 100% の CPU を消費する状況が発生する可能性があります。これは、実稼働の Web アプリで一度発生しました。デバッグするのは楽しいことではありません。

メソッドをロックするか、代わりに a を使用できますConcurrentDictionary<K,V>

「スレッドセーフ」をさまざまな方法で定義できることに注意してください。プロパティと属性を見つける操作全体をアトミックにしたい場合は、メソッドをロックする必要があります。ただし、これによりアプリに大量のロックが発生し、パフォーマンスが低下する可能性があることに注意してください。競合状態で作業を 2 回行う可能性があり、辞書が正しく動作することを確認するだけでよい場合は、ConcurrentDictionary を使用することをお勧めします。

于 2013-03-29T18:18:13.447 に答える