📄 scriptobjectbuilder.cs
字号:
// since we're inside the lock, check again just in case.
//
if (ignoreStartingTypeReferences || !_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 dependent references and add them to the ref list.
entries.AddRange(GetScriptReferencesInternal(attr.ExtenderType, typeReferenceStack, false));
}
}
// Get the client script resource values for this type
int order = 0;
// create a new list so we can sort it independently.
//
List<ResourceEntry> newEntries = new List<ResourceEntry>();
for (Type current = type; current != null && current != typeof(object); current = current.BaseType)
{
if (ignoreStartingTypeReferences && (current == type))
{
// Skip the starting type because ScriptPath is being used to override
continue;
}
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);
// 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 (but don't cache if this response is unusual for some reason)
//
if (!ignoreStartingTypeReferences)
{
_cache.Add(type, entries);
}
}
return entries;
}
}
finally
{
// Remove the type as further requests will get the cached reference
typeReferenceStack.Pop();
}
}
/// <summary>
/// Gets the css 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 IEnumerable<string> GetCssReferences(Control control, 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
IList<string> references;
if (_cssCache.TryGetValue(type, out references))
{
return references;
}
// Track this type to prevent circular references
typeReferenceStack.Push(type);
try
{
lock (_sync)
{
// double-checked lock
if (_cssCache.TryGetValue(type, out references))
{
return references;
}
// build the reference list
List<string> referenceList = new List<string>();
// 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 dependent references
referenceList.AddRange(GetCssReferences(control, attr.ExtenderType, typeReferenceStack));
}
}
// Get the client script resource values for this type
List<ResourceEntry> entries = new List<ResourceEntry>();
int order = 0;
for (Type current = type; current != null && current != typeof(object); current = current.BaseType)
{
object[] attrs = Attribute.GetCustomAttributes(current, typeof(ClientCssResourceAttribute), false);
order -= attrs.Length;
foreach (ClientCssResourceAttribute attr in attrs)
{
entries.Add(new ResourceEntry(attr.ResourcePath, current, order + attr.LoadOrder));
}
}
entries.Sort(delegate(ResourceEntry l, ResourceEntry r) { return l.Order.CompareTo(r.Order); });
foreach (ResourceEntry entry in entries)
{
referenceList.Add(control.Page.ClientScript.GetWebResourceUrl(entry.ComponentType, entry.ResourcePath));
}
// Remove duplicates from reference list
Dictionary<string, object> cookies = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
List<string> newReferenceList = new List<string>();
foreach (string refr in referenceList)
{
if (cookies.ContainsKey(refr))
continue;
cookies.Add(refr, null);
newReferenceList.Add(refr);
}
// Create a readonly dictionary to hold the values
references = new ReadOnlyCollection<string>(newReferenceList);
// Cache the reference
_cssCache.Add(type, references);
// return the list
return references;
}
}
finally
{
// Remove the type as further requests will get the cached reference
typeReferenceStack.Pop();
}
}
private struct ResourceEntry
{
public string ResourcePath;
public Type ComponentType;
public int Order;
private string AssemblyName
{
get
{
return ComponentType == null ? "" : ComponentType.Assembly.FullName;
}
}
public ResourceEntry(string path, Type componentType, int order)
{
ResourcePath = path;
ComponentType = componentType;
Order = order;
}
public ScriptReference ToScriptReference()
{
ScriptReference refr = new ScriptReference();
refr.Assembly = AssemblyName;
refr.Name = ResourcePath;
return refr;
}
public override bool Equals(object obj)
{
ResourceEntry other = (ResourceEntry)obj;
return ResourcePath.Equals(other.ResourcePath, StringComparison.OrdinalIgnoreCase)
&& AssemblyName.Equals(other.AssemblyName, StringComparison.OrdinalIgnoreCase);
}
public static bool operator ==(ResourceEntry obj1, ResourceEntry obj2)
{
return obj1.Equals(obj2);
}
public static bool operator !=(ResourceEntry obj1, ResourceEntry obj2)
{
return !obj1.Equals(obj2);
}
public override int GetHashCode()
{
return AssemblyName.GetHashCode() ^ ResourcePath.GetHashCode();
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -