Example #1
0
        /// <summary>
        /// Populate the cache of PropertyInfos for this type
        /// </summary>
        private void PopulatePropertyInfoCacheIfNecessary()
        {
            if (_propertyInfoCache == null)
            {
                _propertyInfoCache = new Dictionary <string, TaskPropertyInfo>(StringComparer.OrdinalIgnoreCase);

                // Use a HybridDictionary because these are usually very small
                _namesOfPropertiesWithRequiredAttribute = new HybridDictionary <string, string>(StringComparer.OrdinalIgnoreCase);
                _namesOfPropertiesWithOutputAttribute   = new HybridDictionary <string, string>(StringComparer.OrdinalIgnoreCase);
                _namesOfPropertiesWithAmbiguousMatches  = new HybridDictionary <string, string>(StringComparer.OrdinalIgnoreCase);

                bool taskTypeImplementsIGeneratedTask = typeof(IGeneratedTask).IsAssignableFrom(_taskFactory.TaskType);
                TaskPropertyInfo[] propertyInfos      = _taskFactory.GetTaskParameters();

                for (int i = 0; i < propertyInfos.Length; i++)
                {
                    // If the task implements IGeneratedTask, we must use the TaskPropertyInfo the factory gives us.
                    // Otherwise, we never have to hand the TaskPropertyInfo back to the task or factory, so we replace
                    // theirs with one of our own that will allow us to cache reflection data per-property.
                    TaskPropertyInfo propertyInfo = propertyInfos[i];
                    if (!taskTypeImplementsIGeneratedTask)
                    {
                        propertyInfo = new ReflectableTaskPropertyInfo(propertyInfo, _taskFactory.TaskType);
                    }

                    try
                    {
                        _propertyInfoCache.Add(propertyInfo.Name, propertyInfo);
                    }
                    catch (ArgumentException)
                    {
                        // We have encountered a duplicate entry in our hashtable; if we had used BindingFlags.IgnoreCase this
                        // would have produced an AmbiguousMatchException. In the old code, before this cache existed,
                        // that wouldn't have been thrown unless and until the project actually tried to set this ambiguous parameter.
                        // So rather than fail here, we store a list of ambiguous names and throw later, when one of them
                        // is requested.
                        _namesOfPropertiesWithAmbiguousMatches[propertyInfo.Name] = String.Empty;
                    }

                    if (propertyInfos[i].Required)
                    {
                        // we have a require attribute defined, keep a record of that
                        _namesOfPropertiesWithRequiredAttribute[propertyInfo.Name] = String.Empty;
                    }

                    if (propertyInfos[i].Output)
                    {
                        // we have a output attribute defined, keep a record of that
                        _namesOfPropertiesWithOutputAttribute[propertyInfo.Name] = String.Empty;
                    }
                }

                // Toss the dictionaries if we can as often they are empty (at least the last three are)
                _propertyInfoCache = (_propertyInfoCache.Count == 0) ? ReadOnlyEmptyDictionary <string, TaskPropertyInfo> .Instance : _propertyInfoCache;
                _namesOfPropertiesWithRequiredAttribute = (_namesOfPropertiesWithRequiredAttribute.Count == 0) ? ReadOnlyEmptyDictionary <string, string> .Instance : _namesOfPropertiesWithRequiredAttribute;
                _namesOfPropertiesWithOutputAttribute   = (_namesOfPropertiesWithOutputAttribute.Count == 0) ? ReadOnlyEmptyDictionary <string, string> .Instance : _namesOfPropertiesWithOutputAttribute;
                _namesOfPropertiesWithAmbiguousMatches  = (_namesOfPropertiesWithAmbiguousMatches.Count == 0) ? ReadOnlyEmptyDictionary <string, string> .Instance : _namesOfPropertiesWithAmbiguousMatches;
            }
        }