将包含属性的上下文传递给TypeConverter

Jam*_*uth 8 c# type-conversion typeconverter typedescriptor icustomtypedescriptor

我正在寻找一种方法将附加信息传递给a TypeConverter,以便为转换提供一些上下文而无需创建自定义构造函数.

传递的额外信息将是原始对象(在编译时称为接口),其中包含我正在转换的属性.它包含自己的属性,这些属性Id对于查找转换相关信息非常有用.

我已经看过ITypeDescriptorContext的文档,但是我还没有找到一个如何实现该接口的明确示例.我也不相信这是我需要的工具.

目前,在我的代码中我打电话:

// For each writeable property in my output class.

// If property has TypeConverterAttribute
var converted = converter.ConvertFrom(propertyFromOriginalObject)

propertyInfo.SetValue(output, converted, null);
Run Code Online (Sandbox Code Playgroud)

我想做的就像是.

// Original object is an interface at compile time.
var mayNewValue = converter.ConvertFrom(originalObject, propertyFromOriginalObject)
Run Code Online (Sandbox Code Playgroud)

我希望能够使用其中一个重载来执行我需要的操作,以便任何自定义转换器都可以从TypeConverter具有自定义构造函数的基类继承,因为通过依赖注入和DependencyResolver.Current.GetService(type)从MVC使用初始化可以使生活更轻松我的转换器.

有任何想法吗?

Sim*_*ier 5

您要使用的方法显然是此重载:TypeConverter.ConvertFrom方法(ITypeDescriptorContext,CultureInfo,Object)

它将允许您传递相当普通的上下文。该Instance属性表示您正在处理的对象实例,而该PropertyDescriptor属性表示要转换的属性值的属性定义。

例如,Winforms属性网格可以做到这一点。

因此,您必须提供自己的上下文。这是一个示例:

public class MyContext : ITypeDescriptorContext
{
    public MyContext(object instance, string propertyName)
    {
        Instance = instance;
        PropertyDescriptor = TypeDescriptor.GetProperties(instance)[propertyName];
    }

    public object Instance { get; private set; }
    public PropertyDescriptor PropertyDescriptor { get; private set; }
    public IContainer Container { get; private set; }

    public void OnComponentChanged()
    {
    }

    public bool OnComponentChanging()
    {
        return true;
    }

    public object GetService(Type serviceType)
    {
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,让我们考虑一个自定义转换器,因为您看到它可以使用一行代码来捕获现有对象的属性值(请注意,此代码与标准的现有ITypeDescriptorContext兼容,例如属性网格,尽管在现实生活中,您必须检查上下文无效):

public class MyTypeConverter : TypeConverter
{
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        // get existing value
        object existingPropertyValue = context.PropertyDescriptor.GetValue(context.Instance);

        // do something useful here
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您要修改此自定义对象:

public class MySampleObject
{
    public MySampleObject()
    {
        MySampleProp = "hello world";
    }

    public string MySampleProp { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

您可以这样调用转换器:

MyTypeConverter tc = new MyTypeConverter();
object newValue = tc.ConvertFrom(new MyContext(new MySampleObject(), "MySampleProp"), null, "whatever");
Run Code Online (Sandbox Code Playgroud)