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 is not thread-safe. And your method GetValidationRules is reading and writing it. If multiple threads call this method, dictionary data may get corrupt. To avoid this, put a lock(...){ ... } that covers all dictionary method calls.

于 2013-03-29T18:17:52.990 回答
3

This could get you in trouble in a multi threaded environment. Generally, the Dictionary<K,V> class is not thread safe. Beyound data corruption or correctness issues, in rare circumstances, if one thread hits the dictionary while it is being resized on another thread, you could get a situation where the thread gets stuck in a loop, eating 100% CPU. This happened to me in a production web app once - not a fun thing to debug.

You could either put a lock around the method, or use a ConcurrentDictionary<K,V> instead.

请注意,我们可以用不同的方式定义“线程安全”。如果您希望查找属性和属性的整个操作是原子的,您应该在方法周围加一个锁。但请注意,这会在应用程序中引入大量锁定,可能会损害性能。如果您可以在竞态条件下完成两次工作,并且只需要确保字典的行为正确,那么 ConcurrentDictionary 就是要走的路。

于 2013-03-29T18:18:13.447 回答