Frage Übergeben eines Kontexts, der Eigenschaften enthält, an einen TypeConverter


Ich bin auf der Suche nach einer Möglichkeit, zusätzliche Informationen an eine TypeConverter um einen Kontext für Konvertierungen bereitzustellen, ohne einen benutzerdefinierten Konstruktor zu erstellen.

Diese zusätzlichen Informationen wären ursprüngliches Objekt (das zur Kompilierungszeit als Schnittstelle bekannt ist), das die Eigenschaft enthält, die ich konvertiere. Es enthält eigene Eigenschaften wie Id Dies ist nützlich für Nachschlagevorgänge, um verwandte Informationen zu konvertieren.

Ich habe mir die Dokumentation für ITypeDescriptorContext aber ich habe kein klares Beispiel dafür gefunden, wie diese Schnittstelle implementiert werden kann. Ich bin auch nicht überzeugt, dass es das Werkzeug ist, das ich brauche.

Im Moment rufe ich in meinem Code an:

// For each writeable property in my output class.

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

propertyInfo.SetValue(output, converted, null);

Was ich gerne machen würde ist etwas wie.

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

Ich möchte in der Lage sein, eine der Überladungen zu verwenden, um das zu tun, was ich brauche, damit benutzerdefinierte Konverter davon erben können TypeConverter statt einer Basisklasse mit einem benutzerdefinierten Konstruktor, der das Leben mit der Abhängigkeitsinjektion und -nutzung erleichtert DependencyResolver.Current.GetService(type) von MVC, um meinen Konverter zu initialisieren.

Irgendwelche Ideen?


7
2018-02-27 13:10


Ursprung


Antworten:


Die Methode, die Sie verwenden möchten, ist eindeutig diese Überladung: TypeConverter.ConvertFrom-Methode (ITypeDescriptorContext, CultureInfo, Object)

Es ermöglicht Ihnen, einen ziemlich generischen Kontext zu übergeben. Das Instance Eigenschaft repräsentiert die Objektinstanz, an der Sie gerade arbeiten, und die PropertyDescriptor Eigenschaft repräsentiert die Eigenschaftsdefinition des zu konvertierenden Eigenschaftswerts.

Das Winforms-Eigenschaftenraster führt genau das aus.

Sie müssen also Ihren eigenen Kontext angeben. Hier ist ein Beispiel:

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;
    }
}

Betrachten wir nun einen benutzerdefinierten Konverter, der, wie Sie sehen, den Eigenschaftswert des vorhandenen Objekts mit einer Codezeile erfassen kann (beachten Sie, dass dieser Code mit dem vorhandenen ITypeDescriptorContext vergleichbar ist wie das Eigenschaftenraster, obwohl Sie den Kontext überprüfen müssen für Nichtigkeit):

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
        ...
    }
}

Wenn Sie dieses benutzerdefinierte Objekt jetzt ändern:

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

    public string MySampleProp { get; set; }
}

Sie können den Konverter folgendermaßen aufrufen:

MyTypeConverter tc = new MyTypeConverter();
object newValue = tc.ConvertFrom(new MyContext(new MySampleObject(), "MySampleProp"), null, "whatever");

4
2018-03-03 06:42