在 VS10 .NET 表单中寻找更动态的设计器 TypeConverter 序列化
Looking for a more dynamic designer TypeConverter serialization in a VS10 .NET form
我有一个 class 的列表,我使用以下代码将其序列化为设计器生成的代码:
internal class TargetSettingsConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(InstanceDescriptor) || base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor) && value is ControlListManager.TargetSettings)
{
ConstructorInfo constructor = typeof(ControlListManager.TargetSettings).GetConstructor(new[] { typeof(object), typeof(string), typeof(DisplayModes), typeof(bool), typeof(int), typeof(int), typeof(int) });
var target = value as ControlListManager.TargetSettings;
var descriptor = new InstanceDescriptor(constructor, new[] { target.Target, target.Text, target.DisplayMode, target.Fade, target.HideTimeout, target.PaddingX, target.PaddingY }, true);
return descriptor;
}
if (culture == null) { culture = CultureInfo.CurrentCulture; }
return base.ConvertTo(context, culture, value, destinationType);
}
}
到目前为止效果很好,但令我困扰的是我必须单独指定类型和值。
我的第一个想法是改用 GetConstructors()。但是,价值观的问题仍然存在。我真的对这个问题感到困惑,因为我实际上在不知道参数数量的情况下编写函数 - 或者仅当它是“硬编码”时才知道。
有没有人知道如何做得更好?
编辑:数据class
[TypeConverter(typeof(TargetSettingsConverter))]
public class TargetSettings : IEquatable<TargetSettings>
{
public object Target = new { };
public string Text;
public DisplayModes DisplayMode = DisplayModes.FollowXY;
public bool Fade = true;
public int HideTimeout;
public int PaddingX;
public int PaddingY;
public bool Equals(TargetSettings other)
{
return other != null && (Target.Equals(other.Target));
}
public override bool Equals(object obj)
{
if (obj == null) { return false; }
TargetSettings objAsPart = obj as TargetSettings;
if (objAsPart == null) { return false; }
return Equals(objAsPart);
}
public override int GetHashCode()
{
return Target.GetHashCode();
}
public TargetSettings(object target, string text = "", DisplayModes displayMode = DisplayModes.FollowXY, bool fade = true, int hideTimeout = 0, int paddingX = 0, int paddingY = 0)
{
Target = target;
Text = text;
DisplayMode = displayMode;
Fade = fade;
HideTimeout = hideTimeout;
PaddingX = paddingX;
PaddingY = paddingY;
}
}
根据您的问题,您希望使代码针对类型和值更加动态。
因为你要转换的类型和值都是字段类型。我建议你使用反射来做。
您可以获得所有的字段类型如下:
Type []tarr = typeof(TargetSettings).GetFields().Select(i => i.FieldType).ToArray();
ConstructorInfo constructor = typeof(TargetSettings).GetConstructor(tarr);
您可以获取所有字段值如下:
object []oarr= typeof(TargetSettings).GetFields().Select(i => i.GetValue(target)).ToArray();
var descriptor = new InstanceDescriptor(constructor, oarr, true);
完整代码:
internal class TargetSettingsConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(InstanceDescriptor) || base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor) && value is TargetSettings)
{
Type []tarr = typeof(TargetSettings).GetFields().Select(i => i.FieldType).ToArray();
ConstructorInfo constructor = typeof(TargetSettings).GetConstructor(tarr);
var target = value as TargetSettings;
object []oarr= typeof(TargetSettings).GetFields().Select(i => i.GetValue(target)).ToArray();
var descriptor = new InstanceDescriptor(constructor, oarr, true);
return descriptor;
}
if (culture == null) { culture = CultureInfo.CurrentCulture; }
return base.ConvertTo(context, culture, value, destinationType);
}
}
[TypeConverter(typeof(TargetSettingsConverter))]
public class TargetSettings : IEquatable<TargetSettings>
{
public object Target = new { };
public string Text;
public DisplayModes DisplayMode = DisplayModes.FollowXY;
public bool Fade = true;
public int HideTimeout;
public int PaddingX;
public int PaddingY;
public bool Equals(TargetSettings other)
{
return other != null && (Target.Equals(other.Target));
}
public override bool Equals(object obj)
{
if (obj == null) { return false; }
TargetSettings objAsPart = obj as TargetSettings;
if (objAsPart == null) { return false; }
return Equals(objAsPart);
}
public override int GetHashCode()
{
return Target.GetHashCode();
}
public TargetSettings(object target, string text = "", DisplayModes displayMode = DisplayModes.FollowXY, bool fade = true, int hideTimeout = 0, int paddingX = 0, int paddingY = 0)
{
Target = target;
Text = text;
DisplayMode = displayMode;
Fade = fade;
HideTimeout = hideTimeout;
PaddingX = paddingX;
PaddingY = paddingY;
}
}
public enum DisplayModes
{
FollowXY
}
我有一个 class 的列表,我使用以下代码将其序列化为设计器生成的代码:
internal class TargetSettingsConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(InstanceDescriptor) || base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor) && value is ControlListManager.TargetSettings)
{
ConstructorInfo constructor = typeof(ControlListManager.TargetSettings).GetConstructor(new[] { typeof(object), typeof(string), typeof(DisplayModes), typeof(bool), typeof(int), typeof(int), typeof(int) });
var target = value as ControlListManager.TargetSettings;
var descriptor = new InstanceDescriptor(constructor, new[] { target.Target, target.Text, target.DisplayMode, target.Fade, target.HideTimeout, target.PaddingX, target.PaddingY }, true);
return descriptor;
}
if (culture == null) { culture = CultureInfo.CurrentCulture; }
return base.ConvertTo(context, culture, value, destinationType);
}
}
到目前为止效果很好,但令我困扰的是我必须单独指定类型和值。
我的第一个想法是改用 GetConstructors()。但是,价值观的问题仍然存在。我真的对这个问题感到困惑,因为我实际上在不知道参数数量的情况下编写函数 - 或者仅当它是“硬编码”时才知道。
有没有人知道如何做得更好?
编辑:数据class
[TypeConverter(typeof(TargetSettingsConverter))]
public class TargetSettings : IEquatable<TargetSettings>
{
public object Target = new { };
public string Text;
public DisplayModes DisplayMode = DisplayModes.FollowXY;
public bool Fade = true;
public int HideTimeout;
public int PaddingX;
public int PaddingY;
public bool Equals(TargetSettings other)
{
return other != null && (Target.Equals(other.Target));
}
public override bool Equals(object obj)
{
if (obj == null) { return false; }
TargetSettings objAsPart = obj as TargetSettings;
if (objAsPart == null) { return false; }
return Equals(objAsPart);
}
public override int GetHashCode()
{
return Target.GetHashCode();
}
public TargetSettings(object target, string text = "", DisplayModes displayMode = DisplayModes.FollowXY, bool fade = true, int hideTimeout = 0, int paddingX = 0, int paddingY = 0)
{
Target = target;
Text = text;
DisplayMode = displayMode;
Fade = fade;
HideTimeout = hideTimeout;
PaddingX = paddingX;
PaddingY = paddingY;
}
}
根据您的问题,您希望使代码针对类型和值更加动态。
因为你要转换的类型和值都是字段类型。我建议你使用反射来做。
您可以获得所有的字段类型如下:
Type []tarr = typeof(TargetSettings).GetFields().Select(i => i.FieldType).ToArray();
ConstructorInfo constructor = typeof(TargetSettings).GetConstructor(tarr);
您可以获取所有字段值如下:
object []oarr= typeof(TargetSettings).GetFields().Select(i => i.GetValue(target)).ToArray();
var descriptor = new InstanceDescriptor(constructor, oarr, true);
完整代码:
internal class TargetSettingsConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(InstanceDescriptor) || base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor) && value is TargetSettings)
{
Type []tarr = typeof(TargetSettings).GetFields().Select(i => i.FieldType).ToArray();
ConstructorInfo constructor = typeof(TargetSettings).GetConstructor(tarr);
var target = value as TargetSettings;
object []oarr= typeof(TargetSettings).GetFields().Select(i => i.GetValue(target)).ToArray();
var descriptor = new InstanceDescriptor(constructor, oarr, true);
return descriptor;
}
if (culture == null) { culture = CultureInfo.CurrentCulture; }
return base.ConvertTo(context, culture, value, destinationType);
}
}
[TypeConverter(typeof(TargetSettingsConverter))]
public class TargetSettings : IEquatable<TargetSettings>
{
public object Target = new { };
public string Text;
public DisplayModes DisplayMode = DisplayModes.FollowXY;
public bool Fade = true;
public int HideTimeout;
public int PaddingX;
public int PaddingY;
public bool Equals(TargetSettings other)
{
return other != null && (Target.Equals(other.Target));
}
public override bool Equals(object obj)
{
if (obj == null) { return false; }
TargetSettings objAsPart = obj as TargetSettings;
if (objAsPart == null) { return false; }
return Equals(objAsPart);
}
public override int GetHashCode()
{
return Target.GetHashCode();
}
public TargetSettings(object target, string text = "", DisplayModes displayMode = DisplayModes.FollowXY, bool fade = true, int hideTimeout = 0, int paddingX = 0, int paddingY = 0)
{
Target = target;
Text = text;
DisplayMode = displayMode;
Fade = fade;
HideTimeout = hideTimeout;
PaddingX = paddingX;
PaddingY = paddingY;
}
}
public enum DisplayModes
{
FollowXY
}