You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
13 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace GeoSigma.SigmaDrawerStyle.Converter
{
public abstract class BaseConverter<T> : TypeConverter
where T : TypeConverter, new()
{
#region Proxy
private T _proxy = new T();
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return _proxy.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return _proxy.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return _proxy.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
return _proxy.ConvertTo(context, culture, value, destinationType);
}
public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
{
return _proxy.CreateInstance(context, propertyValues);
}
public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
{
return _proxy.GetCreateInstanceSupported(context);
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
return _proxy.GetStandardValues(context);
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return _proxy.GetStandardValuesExclusive(context);
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return _proxy.GetStandardValuesSupported(context);
}
public override bool IsValid(ITypeDescriptorContext context, object value)
{
return _proxy.IsValid(context, value);
}
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return _proxy.GetPropertiesSupported(context);
}
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
return _proxy.GetProperties(context, value, attributes);
}
#endregion
}
public class BaseTypeConverter : BaseConverter<TypeConverter>
{
}
public class BaseExpandableConverter : BaseConverter<ExpandableObjectConverter>
{
}
public class BaseExpandableReadonlyConverter : BaseConverter<ExpandableObjectConverter>
{
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context,
object value, Attribute[] attributes)
{
Type type = typeof(System.ComponentModel.ReadOnlyAttribute);
PropertyDescriptorCollection descs = TypeDescriptor.GetProperties(value, attributes);
for (int i = 0;i < descs.Count; i++)
{
PropertyDescriptorCollection descsCol = TypeDescriptor.GetProperties(descs[i], attributes);
var prop = descsCol["IsReadOnly"];
prop.SetValue(type, true);
}
//AttributeCollection attrs = descs["ReadOnly"].Attributes;
//FieldInfo fld = type.GetField("isReadOnly", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.CreateInstance);
//fld.SetValue(attrs[type], true);
//Type memberDescriptorType = typeof(MemberDescriptor);
//FieldInfo memberDescriptorFieldInfo = memberDescriptorType.GetField("IsReadOnly"
// , BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.CreateInstance);
//Type type = value.GetType();
//string strType = type.ToString();
////Type.GetType(strType);
//var model = Activator.CreateInstance(type);
//PropertyInfo[] properties = type.GetProperties();
//for (int i=0;i< properties.Length; i++)
//{
// Trace.WriteLine(properties[i].Name);
//}
//properties[0].SetValue(model, true, null);
//FieldInfo fld = type.GetField("IsReadOnly", BindingFlags.Static | BindingFlags.Public);
//PropertyDescriptorCollection cols = TypeDescriptor.GetProperties(value, attributes);
//FieldInfo[] fieldInfos = type.GetFields();
//for (int i = 0; i < cols.Count; i++)
//{
// var vv = cols[i].GetType().GetRuntimeField("IsReadOnly");
// var old = fld.GetValue(cols[i]);
// fld.SetValue(cols[i], true);
//}
//return cols;
return base.GetProperties(context, value, attributes);
}
}
public class BaseCollectionConverter : BaseConverter<CollectionConverter>
{
#region ExpandableCollectionPropertyDescriptor
public class ExpandableCollectionPropertyDescriptor : PropertyDescriptor
{
private IList collection;
private readonly int _index;
public int Index { get { return _index; } }
/// <summary>
/// Initializes a new instance of the <see cref="ExpandableCollectionPropertyDescriptor"/> class.
/// </summary>
/// <param name="coll"></param>
/// <param name="idx"></param>
public ExpandableCollectionPropertyDescriptor(IList coll, int idx)
: base("ExpandableCollectionPropertyDescriptor", null)
{
collection = coll;
_index = idx;
}
public override string DisplayName => GetDisplayName(collection, _index);
private static string GetDisplayName(IList list, int index)
{
return new StringBuilder()
.Append('\t', list.Count - index)
.AppendFormat("[{0}] {1}", index, CSharpName(list[index].GetType()))
.ToString();
}
private static string CSharpName(Type type)
{
var dnAttribute = type.GetCustomAttributes(typeof(DisplayNameAttribute), true)
.FirstOrDefault() as DisplayNameAttribute;
if (dnAttribute != null)
{
return dnAttribute.DisplayName;
}
var sb = new StringBuilder();
var name = type.Name;
if (!type.IsGenericType)
return name;
sb.Append(name.Substring(0, name.IndexOf('`')));
sb.Append("<");
sb.Append(string.Join(", ", type.GetGenericArguments()
.Select(CSharpName)));
sb.Append(">");
return sb.ToString();
}
public override bool CanResetValue(object component)
{
return true;
}
public override Type ComponentType
{
get { return this.collection.GetType(); }
}
public override object GetValue(object component)
{
return collection[_index];
}
public override bool IsReadOnly
{
get { return false; }
}
public override string Name
{
get { return _index.ToString(CultureInfo.InvariantCulture); }
}
public override Type PropertyType
{
get { return collection[_index].GetType(); }
}
public override void ResetValue(object component)
{
}
public override bool ShouldSerializeValue(object component)
{
return true;
}
public override void SetValue(object component, object value)
{
collection[_index] = value;
}
}
#endregion
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
if (value is IList list && list.Count > 0)
{
var items = new PropertyDescriptorCollection(null);
for (int i = 0; i < list.Count; i++)
{
object item = list[i];
ExpandableCollectionPropertyDescriptor desc = new ExpandableCollectionPropertyDescriptor(list, i);
items.Add(desc);
}
return items.Sort(new DescComparer());
}
return base.GetProperties(context, value, attributes);
}
public class DescComparer : IComparer
{
public int Compare(object x, object y)
{
// 这里是你的自定义排序逻辑
// 例如,我们可以按照属性名的长度进行排序
ExpandableCollectionPropertyDescriptor pdx = x as ExpandableCollectionPropertyDescriptor;
ExpandableCollectionPropertyDescriptor pdy = y as ExpandableCollectionPropertyDescriptor;
return pdx.Index.CompareTo(pdy.Index);
}
}
}
public class BaseDropDownConverter : BaseConverter<TypeConverter>
{
public override Boolean GetStandardValuesSupported(ITypeDescriptorContext context) { return true; }
public override Boolean GetStandardValuesExclusive(ITypeDescriptorContext context) { return true; }
}
public abstract class EnumConverter<T> : BaseDropDownConverter
where T : struct, IConvertible //Enum
{
protected abstract Dictionary<T, string> CreateMaps();
private volatile Dictionary<T, string> maps;
private volatile StandardValuesCollection values;
private Dictionary<T, string> GetMap()
{
if (maps == null)
{
maps = CreateMaps();
}
return maps;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
return values ?? (values = new StandardValuesCollection(GetMap().Keys));
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value != null && value is string)
{
foreach (var item in maps)
{
if (value.Equals(item.Value))
{
if (context.PropertyDescriptor.PropertyType == typeof(int))
{
return Convert.ToInt32(item.Key);
}
else
{
return item.Key;
}
}
}
}
return base.ConvertFrom(context, culture, value);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
if (value is int iValue)
{
var eValue = (T)Enum.ToObject(typeof(T), iValue);
if (GetMap().ContainsKey(eValue))
{
return GetMap()[eValue];
}
}
if (value is T tValue)
{
if (GetMap().ContainsKey(tValue))
{
return GetMap()[tValue];
}
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}