/// <summary> /// /// </summary> /// <param name="obj"></param> /// <returns></returns> public override bool Equals(object obj) { ResourceEntry other = (ResourceEntry)obj; return(String.Compare(RefKey, other.RefKey, true, CultureInfo.CurrentCulture) == 0); }
/// <summary> /// Gets the script references for a type and walks the type's dependencies with circular-reference checking /// </summary> /// <param name="type"></param> /// <param name="typeReferenceStack"></param> /// <returns></returns> private static List<ResourceEntry> GetScriptReferencesInternal(Type type, Stack<Type> typeReferenceStack) { // Verify no circular references if (typeReferenceStack.Contains(type)) { throw new InvalidOperationException("Circular reference detected."); } // Look for a cached set of references outside of the lock for perf. // List<ResourceEntry> entries; if (_cache.TryGetValue(type, out entries)) { return entries; } // Track this type to prevent circular references typeReferenceStack.Push(type); try { lock (_sync) { // since we're inside the lock, check again just in case. // if (!_cache.TryGetValue(type, out entries)) { entries = new List<ResourceEntry>(); // Get the required scripts by type List<RequiredScriptAttribute> requiredScripts = new List<RequiredScriptAttribute>(); foreach (RequiredScriptAttribute attr in type.GetCustomAttributes(typeof(RequiredScriptAttribute), true)) { requiredScripts.Add(attr); } requiredScripts.Sort(delegate(RequiredScriptAttribute left, RequiredScriptAttribute right) { return left.LoadOrder.CompareTo(right.LoadOrder); }); foreach (RequiredScriptAttribute attr in requiredScripts) { if (attr.ExtenderType != null) { // extrapolate dependant references and add them to the ref list. entries.AddRange(GetScriptReferencesInternal(attr.ExtenderType, typeReferenceStack)); } } // Get the client script resource values for this type int order = 0; // create a new list so we can sort it independantly. // List<ResourceEntry> newEntries = new List<ResourceEntry>(); for (Type current = type; current != null && current != typeof(object); current = current.BaseType) { object[] attrs = Attribute.GetCustomAttributes(current, typeof(ClientScriptResourceAttribute), false); order -= attrs.Length; foreach (ClientScriptResourceAttribute attr in attrs) { ResourceEntry re = new ResourceEntry(attr.ResourcePath, current, order + attr.LoadOrder, attr.Cacheability); // check for dups in the list. // if (!entries.Contains(re) && !newEntries.Contains(re)) { newEntries.Add(re); } } } // sort the list and add it to the array. // newEntries.Sort(delegate(ResourceEntry l, ResourceEntry r) { return l.Order.CompareTo(r.Order); }); entries.AddRange(newEntries); // Cache the reference list and return // _cache.Add(type, entries); } return entries; } } finally { // Remove the type as further requests will get the cached reference typeReferenceStack.Pop(); } }
/// <summary> /// Gets the script references for a type and walks the type's dependencies with circular-reference checking /// </summary> /// <param name="type"></param> /// <param name="typeReferenceStack"></param> /// <returns></returns> private static List <ResourceEntry> GetScriptReferencesInternal(Type type, Stack <Type> typeReferenceStack) { // Verify no circular references if (typeReferenceStack.Contains(type)) { throw new InvalidOperationException("Circular reference detected."); } // Look for a cached set of references outside of the lock for perf. // List <ResourceEntry> entries; if (_cache.TryGetValue(type, out entries)) { return(entries); } // Track this type to prevent circular references typeReferenceStack.Push(type); try { lock (_sync) { // since we're inside the lock, check again just in case. // if (!_cache.TryGetValue(type, out entries)) { entries = new List <ResourceEntry>(); // Get the required scripts by type List <RequiredScriptAttribute> requiredScripts = new List <RequiredScriptAttribute>(); foreach (RequiredScriptAttribute attr in type.GetCustomAttributes(typeof(RequiredScriptAttribute), true)) { requiredScripts.Add(attr); } requiredScripts.Sort(delegate(RequiredScriptAttribute left, RequiredScriptAttribute right) { return(left.LoadOrder.CompareTo(right.LoadOrder)); }); foreach (RequiredScriptAttribute attr in requiredScripts) { if (attr.ExtenderType != null) { // extrapolate dependant references and add them to the ref list. entries.AddRange(GetScriptReferencesInternal(attr.ExtenderType, typeReferenceStack)); } } // Get the client script resource values for this type int order = 0; // create a new list so we can sort it independantly. // List <ResourceEntry> newEntries = new List <ResourceEntry>(); for (Type current = type; current != null && current != typeof(object); current = current.BaseType) { object[] attrs = Attribute.GetCustomAttributes(current, typeof(ClientScriptResourceAttribute), false); order -= attrs.Length; foreach (ClientScriptResourceAttribute attr in attrs) { ResourceEntry re = new ResourceEntry(attr.ResourcePath, current, order + attr.LoadOrder, attr.Cacheability); // check for dups in the list. // if (!entries.Contains(re) && !newEntries.Contains(re)) { newEntries.Add(re); } } } // sort the list and add it to the array. // newEntries.Sort(delegate(ResourceEntry l, ResourceEntry r) { return(l.Order.CompareTo(r.Order)); }); entries.AddRange(newEntries); // Cache the reference list and return // _cache.Add(type, entries); } return(entries); } } finally { // Remove the type as further requests will get the cached reference typeReferenceStack.Pop(); } }