Added HhyperDescriptor, sorting backgroundsprites according to texture
This commit is contained in:
126
Hyper.ComponentModel/HyperTypeDescriptionProvider.cs
Normal file
126
Hyper.ComponentModel/HyperTypeDescriptionProvider.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
namespace Hyper.ComponentModel
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
|
||||
public sealed class HyperTypeDescriptionProvider : TypeDescriptionProvider
|
||||
{
|
||||
private static readonly Dictionary<Type, ICustomTypeDescriptor> descriptors = new Dictionary<Type, ICustomTypeDescriptor>();
|
||||
private static readonly Dictionary<Type, TypeDescriptionProvider> providers = new Dictionary<Type, TypeDescriptionProvider>();
|
||||
|
||||
public static void Add(Type type)
|
||||
{
|
||||
lock (descriptors)
|
||||
{
|
||||
if (!providers.ContainsKey(type))
|
||||
{
|
||||
// determine if the base type was already added
|
||||
// if so, remove it before adding sub-type
|
||||
// (if a sub-type is added after its base type, infinite recursion occurs in GetTypeDescriptor())
|
||||
var baseFound = false;
|
||||
if (type.BaseType != null && providers.ContainsKey(type.BaseType))
|
||||
{
|
||||
baseFound = true;
|
||||
Remove(type.BaseType);
|
||||
}
|
||||
|
||||
// add the provider for the type
|
||||
var provider = new HyperTypeDescriptionProvider(TypeDescriptor.GetProvider(type));
|
||||
|
||||
TypeDescriptor.AddProvider(provider, type);
|
||||
providers.Add(type, provider);
|
||||
|
||||
// initialize descriptor
|
||||
provider.GetTypeDescriptor(type);
|
||||
|
||||
// if base type was removed, we can now add it back after building the sub-type descriptor
|
||||
if (baseFound)
|
||||
Add(type.BaseType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Remove(Type type)
|
||||
{
|
||||
lock (descriptors)
|
||||
{
|
||||
TypeDescriptor.RemoveProvider(providers[type], type);
|
||||
providers.Remove(type);
|
||||
descriptors.Remove(type);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Clear()
|
||||
{
|
||||
lock (descriptors)
|
||||
{
|
||||
foreach (var provider in providers)
|
||||
TypeDescriptor.RemoveProvider(provider.Value, provider.Key);
|
||||
providers.Clear();
|
||||
descriptors.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private HyperTypeDescriptionProvider()
|
||||
: this(typeof(object))
|
||||
{ }
|
||||
|
||||
private HyperTypeDescriptionProvider(Type type)
|
||||
: this(TypeDescriptor.GetProvider(type))
|
||||
{ }
|
||||
|
||||
private HyperTypeDescriptionProvider(TypeDescriptionProvider parent)
|
||||
: base(parent)
|
||||
{ }
|
||||
|
||||
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
|
||||
{
|
||||
lock (descriptors)
|
||||
{
|
||||
ICustomTypeDescriptor descriptor;
|
||||
if (!descriptors.TryGetValue(objectType, out descriptor))
|
||||
{
|
||||
try
|
||||
{
|
||||
descriptor = BuildDescriptor(objectType);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return base.GetTypeDescriptor(objectType, instance);
|
||||
}
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
[ReflectionPermission(SecurityAction.Assert, Unrestricted = true)]
|
||||
private ICustomTypeDescriptor BuildDescriptor(Type objectType)
|
||||
{
|
||||
// NOTE: "descriptors" already locked here
|
||||
|
||||
// get the parent descriptor and add to the dictionary so that
|
||||
// building the new descriptor will use the base rather than recursing
|
||||
var descriptor = base.GetTypeDescriptor(objectType, null);
|
||||
descriptors.Add(objectType, descriptor);
|
||||
try
|
||||
{
|
||||
// build a new descriptor from this, and replace the lookup
|
||||
descriptor = new HyperTypeDescriptor(descriptor);
|
||||
descriptors[objectType] = descriptor;
|
||||
return descriptor;
|
||||
}
|
||||
catch
|
||||
{ // rollback and throw
|
||||
// (perhaps because the specific caller lacked permissions;
|
||||
// another caller may be successful)
|
||||
descriptors.Remove(objectType);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user