Я создал довольно полный набор инструментов для решения этой проблемы. Есть много шагов, но вот оно:
1) Возвращает исходное значение, если целевой тип назначается из исходного значения.
2) В противном случае создайте преобразователь типов (здесь будут интересные части)
public static TypeConverter GetTypeConverter(Type type)
{
TypeConverterAttribute attribute = (TypeConverterAttribute)Attribute.GetCustomAttribute(type, typeof(TypeConverterAttribute), false);
if (attribute != null)
{
try
{
var converterType = Type.GetType(attribute.ConverterTypeName, false);
if (converterType != null)
{
return (Activator.CreateInstance(converterType) as TypeConverter);
}
}
catch {}
}
return new XamlStringConverter(type);
}
Ничего удивительного здесь. Но обратите внимание, что XamlStringConverter возвращается, если конвертер не найден. Он использует Xaml Parser для конвертации вещей. Поле типа включено в конвертер и содержит тип, переданный конструктору.
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
var strValue = value as string;
if (strValue != null) {
if (this.type == typeof(bool)) {
return bool.Parse(strValue);
}
if (this.type.IsEnum) {
return Enum.Parse(this.type, stringValue, false);
}
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("<ContentControl xmlns='http://schemas.microsoft.com/client/2007' xmlns:c='" + ("clr-namespace:" + this.type.Namespace + ";assembly=" + this.type.Assembly.FullName.Split(new char[] { ',' })[0]) + "'>\n");
stringBuilder.Append("<c:" + this.type.Name + ">\n");
stringBuilder.Append(strValue);
stringBuilder.Append("</c:" + this.type.Name + ">\n");
stringBuilder.Append("</ContentControl>");
ContentControl instance = XamlReader.Load(stringBuilder.ToString()) as ContentControl;
if (instance != null) {
return instance.Content;
}
}
return base.ConvertFrom(context, culture, value);
}