使用静态类访问全局/静态字典时是否有任何问题?

时间:2013-03-29 18:14:32

标签: c#

我为一个小项目创建了一个简单的验证过程。验证规则被创建为类的属性的属性。

我有一个需要传递类类型的静态类。该方法将首先检查给定类的规则集是否已经在字典中,否则,它将使用反射来遍历每个属性。

使用这种方法会有任何问题吗?我担心在多线程环境中访问它可能会导致一些问题。

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

2 个答案:

答案 0 :(得分:3)

Dictionary不是线程安全的。你的方法GetValidationRules正在阅读和编写它。如果多个线程调用此方法,则字典数据可能会损坏。为避免这种情况,请添加一个涵盖所有字典方法调用的lock(...){ ... }

答案 1 :(得分:2)

这可能会让您在多线程环境中遇到麻烦。通常,Dictionary<K,V>类不是线程安全的。 Beyound数据损坏或正确性问题,在极少数情况下,如果一个线程在另一个线程上调整字典时遇到字典,则可能会出现线程陷入循环,占用100%CPU的情况。这在我的生产网络应用程序中发生过一次 - 调试并不是一件有趣的事情。

您可以锁定方法,也可以使用ConcurrentDictionary<K,V>

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