Como: implementar um conversor de tipo

Um conversor de tipo pode ser usado para converter valores entre tipos de dados e para auxiliar a configuração de propriedade em tempo de design fornecendo a conversão de texto-para-valor ou uma lista drop-down de valores para selecionar de.Se configurado corretamente, um conversor de tipo pode produzir código de configuração de propriedade com um InstanceDescriptor e System.Reflection objetos para fornecer as informações necessárias para produzir código que inicializa a propriedade em tempo de execução do sistema de designer de serialização.

Conversores de tipo para a tradução de valor

Conversores de tipo podem ser usados para conversões de valor de seqüência ou tradução para ou de tipos de dados com suporte em tempo de design e em tempo de execução.Conversores de tipo permitem que um valor de propriedade a ser representada como texto para o usuário em um host como um navegador de propriedade em um designer de formulários, e eles podem converter o texto inserido pelo usuário em um valor do tipo de dados apropriado.

Tipos de dados mais nativos (Int32, String, tipos de enumeração e outros) ter conversores de tipo de padrão que fornecem conversões de valor de seqüência e executam verificações de validação.Os conversores de tipo padrão estão na System.ComponentModel espaço para nome e são nomeados TypeConverterNameConverter.Você pode estender um conversor de tipo quando a funcionalidade padrão não é adequada para os seus fins ou implementar um conversor de tipo personalizado quando você define um tipo personalizado que não possui um conversor de tipos associados.

ObservaçãoObservação

A TypeConverterAttribute atributo geralmente é aplicado a uma propriedade ou um membro de dados para associá-lo um conversor de tipo.Se um TypeConverterAttribute é aplicado a um tipo, ele não precisa ser reaplicadas para propriedades ou dados membros desse tipo.

A implementação de um conversor de tipos é independente de qualquer funcionalidade da interface do usuário.Portanto, o conversor do mesmo tipo pode ser aplicado no Windows Forms e formulários da Web.

Para implementar um conversor de tipo simples que pode converter uma seqüência de caracteres para um ponto

  1. Definir uma classe que deriva de TypeConverter.

  2. Substituir o CanConvertFrom método que especifica o tipo o conversor pode converter do.Este método está sobrecarregado.

  3. Substituir o ConvertFrom método que implementa a conversão.Este método está sobrecarregado.

  4. Substituir o CanConvertTo método que especifica o tipo o conversor pode converter para.Não é necessário substituir esse método para conversão para um tipo de seqüência de caracteres.Este método está sobrecarregado.

  5. Substituir o ConvertTo método que implementa a conversão.Este método está sobrecarregado.

  6. Substituir o IsValid(ITypeDescriptorContext, Object) método que executa a validação.Este método está sobrecarregado.

O exemplo de código a seguir implementa um conversor de tipo que converte um String digitar em um Point tipo e um Point em um String.O CanConvertTo e IsValid(ITypeDescriptorContext, Object) métodos não são substituídos neste exemplo.

Option Explicit 
Option Strict

Imports System
Imports System.ComponentModel
Imports System.Globalization
Imports System.Drawing

Public Class PointConverter
   Inherits TypeConverter
   
   ' Overrides the CanConvertFrom method of TypeConverter.
   ' The ITypeDescriptorContext interface provides the context for the
   ' conversion. Typically, this interface is used at design time to 
   ' provide information about the design-time container.
   Public Overrides Overloads Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean
      If sourceType Is GetType(String) Then
         Return True
      End If
      Return MyBase.CanConvertFrom(context, sourceType)
   End Function
   
   ' Overrides the ConvertFrom method of TypeConverter.
   Public Overrides Overloads Function ConvertFrom(context As ITypeDescriptorContext, culture As CultureInfo, value As Object) As Object
      If TypeOf value Is String Then
         Dim v As String() = CStr(value).Split(New Char() {","c})
         Return New Point(Integer.Parse(v(0)), Integer.Parse(v(1)))
      End If
      Return MyBase.ConvertFrom(context, culture, value)
   End Function
   
   ' Overrides the ConvertTo method of TypeConverter.
   Public Overrides Overloads Function ConvertTo(context As ITypeDescriptorContext, culture As CultureInfo, value As Object, destinationType As Type) As Object
      If destinationType Is GetType(String) Then
         Return CType(value, Point).X & "," & CType(value, Point).Y
      End If
      Return MyBase.ConvertTo(context, culture, value, destinationType)
   End Function
End Class
using System;
using System.ComponentModel;
using System.Globalization;
using System.Drawing;

public class PointConverter : TypeConverter {
   // Overrides the CanConvertFrom method of TypeConverter.
   // The ITypeDescriptorContext interface provides the context for the
   // conversion. Typically, this interface is used at design time to 
   // provide information about the design-time container.
   public override bool CanConvertFrom(ITypeDescriptorContext context, 
      Type sourceType) {
      
      if (sourceType == typeof(string)) {
         return true;
      }
      return base.CanConvertFrom(context, sourceType);
   }
   // Overrides the ConvertFrom method of TypeConverter.
   public override object ConvertFrom(ITypeDescriptorContext context, 
      CultureInfo culture, object value) {
      if (value is string) {
         string[] v = ((string)value).Split(new char[] {','});
         return new Point(int.Parse(v[0]), int.Parse(v[1]));
      }
      return base.ConvertFrom(context, culture, value);
   }
   // Overrides the ConvertTo method of TypeConverter.
   public override object ConvertTo(ITypeDescriptorContext context, 
      CultureInfo culture, object value, Type destinationType) {  
      if (destinationType == typeof(string)) {
         return ((Point)value).X + "," + ((Point)value).Y;
      }
      return base.ConvertTo(context, culture, value, destinationType);
   }
}

Conversores de tipo que fornecem uma lista de valores padrão para uma janela de propriedades

Um conversor de tipos pode fornecer uma lista de valores para um tipo em um controle de janela de propriedades.Quando um conversor de tipo fornece um conjunto de valores padrão para um tipo, o campo de entrada de valor para uma propriedade do tipo associado em um controle de janela Propriedades exibe uma seta para baixo que exibe uma lista de valores para definir o valor da propriedade para quando clicado.

Quando uma propriedade do tipo que este conversor de tipo está associado é selecionada em um navegador de propriedade do ambiente de tempo de design, o campo de entrada valor conterá um botão que exibe uma lista suspensa dos valores padrão para o tipo de propriedade que você pode selecionar.

Para implementar um conversor de tipo simples que fornece uma lista suspensa de valores padrão em um navegador de propriedade

  1. Definir uma classe que deriva de TypeConverter.

  2. Substituir o GetStandardValuesSupported método e o retorno de true.

  3. Substituir o GetStandardValues método e retornar um TypeConverter.StandardValuesCollection que contém os valores padrão para o tipo de propriedade.Os valores padrão para uma propriedade devem ser do mesmo tipo que a própria propriedade.

  4. Substituir o CanConvertFrom método e o retorno de true para um sourceType o valor do parâmetro do tipo string.

  5. Substituir o ConvertFrom método e retornar o valor apropriado para a propriedade se baseia o value parâmetro.

  6. Aplicar uma TypeConverterAttribute que indica o tipo de seu conversor de tipo para o tipo que você está fornecendo um conjunto de valores padrão para.

O exemplo a seguir demonstra um conversor de tipos que fornece uma lista de valores padrão para um controle de janela de propriedades para uma propriedade do tipo que está associado.O conversor de tipos exemplo suporta propriedades do tipo inteiro, com o qual foi associada.Para usar o exemplo em Visual Studio, compilar o código para uma biblioteca de classes e adicione o IntStandardValuesControl componente para o caixa de ferramentas.Adicionar uma instância da IntStandardValuesControl a um formulário no modo de design e role para a TestInt propriedade na janela Propriedades enquanto o controle esteja selecionado.Selecionando o campo de entrada de valor para a propriedade exibe uma seta para baixo que exibe uma lista drop-down de valores padrão quando clicado.Inserir um valor inteiro adicionar o valor à lista de valores padrão e defina a propriedade para o valor especificado.

using System;
using System.ComponentModel;
using System.Collections;
using System.Drawing;
using System.Windows.Forms;

namespace StandardValuesTest
{  
    public class StandardValuesIntConverter : System.ComponentModel.TypeConverter
    {
        private ArrayList values;
        public StandardValuesIntConverter()
        {
            // Initializes the standard values list with defaults.
            values = new ArrayList(new int[] { 1, 2, 3, 4, 5 });
        }

        // Indicates this converter provides a list of standard values.
        public override bool GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext context)
        {
            return true;
        }

        // Returns a StandardValuesCollection of standard value objects.
        public override System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(System.ComponentModel.ITypeDescriptorContext context)
        {        
            // Passes the local integer array.
            StandardValuesCollection svc = 
                new StandardValuesCollection(values);       
            return svc;
        }

        // Returns true for a sourceType of string to indicate that 
        // conversions from string to integer are supported. (The 
        // GetStandardValues method requires a string to native type 
        // conversion because the items in the drop-down list are 
        // translated to string.)
        public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType)
        {
            if( sourceType == typeof(string) )
                return true;
            else 
                return base.CanConvertFrom(context, sourceType);
        }

        // If the type of the value to convert is string, parses the string 
        // and returns the integer to set the value of the property to. 
        // This example first extends the integer array that supplies the 
        // standard values collection if the user-entered value is not 
        // already in the array.
        public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if( value.GetType() == typeof(string) )
            {
                // Parses the string to get the integer to set to the property.
                int newVal = int.Parse((string)value);
            
                // Tests whether new integer is already in the list.
                if( !values.Contains(newVal) )
                {
                    // If the integer is not in list, adds it in order.
                    values.Add(newVal);
                    values.Sort();
                }                                
                // Returns the integer value to assign to the property.
                return newVal;
            }
            else
                return base.ConvertFrom(context, culture, value);
        }
    }

    // Provides a test control with an integer property associated with 
    // the StandardValuesIntConverter type converter.
    public class IntStandardValuesControl : System.Windows.Forms.UserControl
    {
        [TypeConverter(typeof(StandardValuesIntConverter))]
        public int TestInt
        {
            get
            {
                return this.integer_field;
            }
            set
            {
                if(value.GetType() == typeof(int))
                    this.integer_field = value;
            }
        }
        private int integer_field = 0;
      
        public IntStandardValuesControl()
        {
            this.BackColor = Color.White;
            this.Size = new Size(472, 80);
        }

        // OnPaint override displays instructions for the example.
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            if(this.DesignMode)
            {
                e.Graphics.DrawString("TypeConverter.GetStandardValues Example Control", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Blue), 5, 5);
                e.Graphics.DrawString("The type converter for the TestInt property of this", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 20);
                e.Graphics.DrawString("component provides a list of standard values to the", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 30);
                e.Graphics.DrawString("Properties window. Setting a value through a property", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 40);
                e.Graphics.DrawString("grid adds it to the list of standard values.", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 50);             
            }
            else
            {
                e.Graphics.DrawString("TypeConverter.GetStandardValues Example Control", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Blue), 5, 5);         
                e.Graphics.DrawString("This control was intended for use in design mode.", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Black), 5, 20);       
            }
        }
    }
}
Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Collections
Imports System.Drawing
Imports System.Windows.Forms

Namespace StandardValuesTest

    Public Class StandardValuesIntConverter
        Inherits System.ComponentModel.TypeConverter

        Private values As ArrayList

        Public Sub New()
            ' Initializes the standard values list with defaults.
            values = New ArrayList(New Integer() {1, 2, 3, 4, 5})
        End Sub 'New

        ' Indicates this type converter provides a list of standard values.
        Public Overloads Overrides Function GetStandardValuesSupported(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
            Return True
        End Function 'GetStandardValuesSupported

        ' Returns a StandardValuesCollection of standard value objects.
        Public Overloads Overrides Function GetStandardValues(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.ComponentModel.TypeConverter.StandardValuesCollection
            ' Passes the local integer array.
            Dim svc As New StandardValuesCollection(values)
            Return svc
        End Function 'GetStandardValues

        ' Returns true for a sourceType of string to indicate that 
        ' conversions from string to integer are supported. (The 
        ' GetStandardValues method requires a string to native type 
        ' conversion because the items in the drop-down list are 
        ' translated to string.)
        Public Overloads Overrides Function CanConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal sourceType As System.Type) As Boolean
            If sourceType Is GetType(String) Then
                Return True
            Else
                Return MyBase.CanConvertFrom(context, sourceType)
            End If
        End Function 'CanConvertFrom

        ' If the type of the value to convert is string, parses the string 
        ' and returns the integer to set the value of the property to. 
        ' This example first extends the integer array that supplies the 
        ' standard values collection if the user-entered value is not 
        ' already in the array.
        Public Overloads Overrides Function ConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object) As Object
            If value.GetType() Is GetType(String) Then
                ' Parses the string to get the integer to set to the property.
                Dim newVal As Integer = Integer.Parse(CStr(value))

                ' Tests whether new integer is already in the list.
                If Not values.Contains(newVal) Then
                    ' If the integer is not in list, adds it in order.
                    values.Add(newVal)
                    values.Sort()
                End If
                ' Returns the integer value to assign to the property.
                Return newVal
            Else
                Return MyBase.ConvertFrom(context, culture, value)
            End If
        End Function 'ConvertFrom
    End Class 'StandardValuesIntConverter

    ' Provides a test control with an integer property associated with the 
    ' StandardValuesIntConverter type converter.
    Public Class IntStandardValuesControl
        Inherits System.Windows.Forms.UserControl

        <TypeConverter(GetType(StandardValuesIntConverter))> _
        Public Property TestInt() As Integer
            Get
                Return Me.integer_field
            End Get
            Set(ByVal Value As Integer)
                If Value.GetType() Is GetType(Integer) Then
                    Me.integer_field = Value
                End If
            End Set
        End Property
        Private integer_field As Integer = 0

        Public Sub New()
            Me.BackColor = Color.White
            Me.Size = New Size(472, 80)
        End Sub 'New

        ' OnPaint override displays instructions for the example.
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            If Me.DesignMode Then
                e.Graphics.DrawString("TypeConverter.GetStandardValues Example Control", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Blue), 5, 5)
                e.Graphics.DrawString("The type converter for the TestInt property of this", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 20)
                e.Graphics.DrawString("component provides a list of standard values to the", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 30)
                e.Graphics.DrawString("Properties window. Setting a value through a property", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 40)
                e.Graphics.DrawString("grid adds it to the list of standard values.", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 50)
            Else
                e.Graphics.DrawString("TypeConverter.GetStandardValues Example Control", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Blue), 5, 5)
                e.Graphics.DrawString("This control was intended for use in design mode.", New Font(FontFamily.GenericMonospace, 10), New SolidBrush(Color.Black), 5, 20)
            End If
        End Sub 'OnPaint
    End Class 'IntStandardValuesControl
End Namespace 'StandardValuesTest

Conversores de tipo que geram código para a inicialização de propriedade em tempo de execução

A.NET Framework fornece a capacidade para gerar código de inicialização propriedade dinâmica em tempo de design que irá inicializar uma propriedade em tempo de execução.

Os desenvolvedores podem criar um conversor de tipo que produz código de inicialização baseado no construtor.Esses conversores de tipo podem gerar o código de construtor dinamicamente usando valores definidos em tempo de design para configurar propriedades de um tipo em tempo de execução.O conversor de tipo implementa a lógica para configurar o tipo e valores de um construtor para a propriedade.

Caso você precise produzir código além um construtor para inicializar uma propriedade, é possível gerar dinamicamente o código implementando um personalizado CodeDomSerializer e a aplicação de um DesignerSerializerAttribute que associa o CodeDomSerializer para um tipo com o tipo.Essa abordagem geralmente é usada somente para cenários em que a geração de código dinamicamente controlado ou personalizados para a inicialização do componente é importante.Para obter mais informações sobre essa abordagem, consulte a documentação para CodeDomSerializer.

Para criar um inicializador de propriedade personalizada de baseado no construtor, você deve associar um conversor de tipo com o tipo da propriedade ao inicializar e o conversor de tipo deve ser capaz de converter em um InstanceDescriptor.

Para implementar um conversor de tipo que produz código de inicialização baseado no construtor de propriedade

  1. Definir uma classe que deriva de TypeConverter.

  2. Substitua o método CanConvertTo.Se a destinationType parâmetro for igual a InstanceDescriptor digite, retornar true.

  3. Substitua o método ConvertTo.Se o destinationType parâmetro é igual a InstanceDescriptor digite, construir e retornar um InstanceDescriptor que representa o construtor e os argumentos do construtor para gerar código para.Para criar um InstanceDescriptor que representa o construtor apropriado e parâmetros, obtenha um ConstructorInfo da Type da propriedade que está sendo inicializados, chamando o GetConstructorou GetConstructors método com a assinatura do método apropriado do construtor você está procurando.Em seguida, criar um novo descritor de instância e passar a ConstructorInfo para o tipo que representa o tipo de construtor para usar, juntamente com uma matriz de objetos de parâmetro que correspondem à assinatura de construtor.

O exemplo a seguir implementa um conversor de tipo que pode gerar código de inicialização baseado no construtor de propriedade para propriedades do tipo Point.

public class PointConverter : TypeConverter 
{
   public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 
   {
      if (destinationType == typeof(InstanceDescriptor)) 
         return true;
      return base.CanConvertTo(context, destinationType);
   }

public override object ConvertTo(ITypeDescriptorContext context, 
CultureInfo culture, object value, Type destinationType) 
{
      // Insert other ConvertTo operations here.
      //
      if (destinationType == typeof(InstanceDescriptor) && 
value is Point) 
   {
         Point pt = (Point)value;

      ConstructorInfo ctor = typeof(Point).GetConstructor(
new Type[] {typeof(int), typeof(int)});
      if (ctor != null) 
      {
         return new InstanceDescriptor(ctor, new object[] {pt.X, pt.Y});
}
}
   return base.ConvertTo(context, culture, value, destinationType);      
}

Compilando o código

  • Quando você desenvolve seu personalizado TypeConverter, é recomendável que você defina o número de compilação para incrementar com cada compilação.Isso impede que as versões mais antigas, armazenadas em cache do seu TypeConverter de ser criado no ambiente de design.

Consulte também

Conceitos

Conversão de tipo generalizada