/// <summary> /// Gets the value of a given property on the given task. /// </summary> internal object GetPropertyValue(ITask task, TaskPropertyInfo property) { ErrorUtilities.VerifyThrowArgumentNull(task, "task"); ErrorUtilities.VerifyThrowArgumentNull(property, "property"); IGeneratedTask generatedTask = task as IGeneratedTask; if (generatedTask != null) { return(generatedTask.GetPropertyValue(property)); } else { ReflectableTaskPropertyInfo propertyInfo = property as ReflectableTaskPropertyInfo; if (propertyInfo != null) { return(propertyInfo.Reflection.GetValue(task, null)); } else { ErrorUtilities.ThrowInternalError("Task does not implement IGeneratedTask and we don't have {0} either.", typeof(ReflectableTaskPropertyInfo).Name); throw new InternalErrorException(); // unreachable } } }
/// <summary> /// Sets the given property on the task. /// </summary> internal void SetPropertyValue(ITask task, TaskPropertyInfo property, object value) { ErrorUtilities.VerifyThrowArgumentNull(task, "task"); ErrorUtilities.VerifyThrowArgumentNull(property, "property"); IGeneratedTask generatedTask = task as IGeneratedTask; if (generatedTask != null) { generatedTask.SetPropertyValue(property, value); } else { ReflectableTaskPropertyInfo propertyInfo = (ReflectableTaskPropertyInfo)property; propertyInfo.Reflection.SetValue(task, value, null); } }
/// <summary> /// Populate the cache of PropertyInfos for this type /// </summary> private void PopulatePropertyInfoCacheIfNecessary() { if (_propertyInfoCache == null) { 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 { if (_propertyInfoCache == null) { _propertyInfoCache = new Dictionary <string, TaskPropertyInfo>(StringComparer.OrdinalIgnoreCase); } _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. if (_namesOfPropertiesWithAmbiguousMatches == null) { _namesOfPropertiesWithAmbiguousMatches = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); } _namesOfPropertiesWithAmbiguousMatches[propertyInfo.Name] = String.Empty; } if (propertyInfos[i].Required) { if (_namesOfPropertiesWithRequiredAttribute == null) { _namesOfPropertiesWithRequiredAttribute = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); } // we have a require attribute defined, keep a record of that _namesOfPropertiesWithRequiredAttribute[propertyInfo.Name] = String.Empty; } if (propertyInfos[i].Output) { if (_namesOfPropertiesWithOutputAttribute == null) { _namesOfPropertiesWithOutputAttribute = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); } // we have a output attribute defined, keep a record of that _namesOfPropertiesWithOutputAttribute[propertyInfo.Name] = String.Empty; } } _propertyInfoCache = _propertyInfoCache ?? ReadOnlyEmptyDictionary <string, TaskPropertyInfo> .Instance; _namesOfPropertiesWithRequiredAttribute = _namesOfPropertiesWithRequiredAttribute ?? ReadOnlyEmptyDictionary <string, string> .Instance; _namesOfPropertiesWithOutputAttribute = _namesOfPropertiesWithOutputAttribute ?? ReadOnlyEmptyDictionary <string, string> .Instance; _namesOfPropertiesWithAmbiguousMatches = _namesOfPropertiesWithAmbiguousMatches ?? ReadOnlyEmptyDictionary <string, string> .Instance; } }