Designer serialização visão geral
Com o designer de serialização, você pode persistir o estado de seus componentes em time de design ou time de execução.
Serialização de objetos
The .NET Framework oferece suporte a vários tipos de serialização, sistema autônomo geração de código, serialização SOAP, serialização binária e serialização de XML.
O Designer de serialização é uma forma especial de serialização que envolve o tipo de persistência de objeto geralmente associado a ferramentas de desenvolvimento.O Designer de Serialização é o processo de conversão de um objeto gráfico em um arquivo de origem que posteriormente pode ser usado para recuperar o objeto gráfico.Um arquivo de origem pode conter código, marcação, ou mesmo informações de uma tabela SQL.O Designer de serialização funciona para todos os objetos de tempo de execução de linguagem comum.
O Designer de serialização é diferente de serialização de objeto típico de várias maneiras:
O objeto realizar a serialização é separado do objeto de time de execução, para que possa ser removida lógica de time de design de um componente.
O esquema de serialização foi desenvolvido sob a suposição de que o objeto será criado em um estado totalmente inicializado e então modificado por meio da propriedade e chamadas de método durante a desserialização.
Propriedades de um objeto com valores que nunca foram definidas no objeto não são serializadas.Por outro lado, o fluxo de desserialização não pode inicializar todos os valores de propriedade.Para obter uma descrição mais detalhada das regras de serialização, consulte a seção "Regras de serialização geral" neste tópico.
Ênfase é colocado na qualidade do conteúdo dentro do fluxo de serialização, em vez da serialização completa de um objeto.Se não houver nenhuma maneira definida para serializar um objeto, esse objeto será transmitido em vez de disparar uma exceção.O Designer de serialização h sistema autônomo maneiras para serializar um objeto em um formulário simples, legível, em vez de sistema autônomo um blob opaco.
O fluxo de serialização pode ter mais dados que é necessário para desserialização.Por exemplo, serialização do código de fonte tem o código do usuário misturado com o código necessário para desserializar um gráfico de objeto.Esse código de usuário deve ser preservado na serialização e passado desserialização.
Observação: |
---|
O Designer de serialização pode ser usada em time de execução e de time de design. |
A tabela a seguir mostra as metas de design preenchidas com o .NET Framework infra-estrutura do Designer de serialização.
Meta de design |
Descrição |
---|---|
Modular |
O processo de serialização pode ser estendido para cobrir a novos tipos de dados e esses tipos de dados podem fornecer descrições úteis, legíveis dos próprios. |
com com facilidade extensível |
O processo de serialização pode ser estendido para cobrir os novos tipos de dados com facilidade. |
Formato neutro |
Objetos podem participar em vários formatos de arquivo diferente e o designer de serialização não está vinculada a um formato de dados específico. |
Arquitetura
Arquitetura do Designer de serialização é baseada em metadados, serializadores e um Gerenciador de serialização.A tabela a seguir descreve da função de cada aspecto da arquitetura.
Aspecto |
Descrição |
---|---|
Atributos de metadados |
Um atributo é usado para relacionar um tipo de T com alguns serializador S.Além disso, a arquitetura oferece suporte a um atributo “ inicialização ” que pode ser usado para instalar um objeto que pode fornecer serializadores para tipos que não os tiver. |
Serializadores |
Um serializador é um objeto que pode serializar um tipo específico ou um intervalo de tipos.Há uma classe base para cada formato de dados.Por exemplo, pode haver um DemoXmlSerializer classe base que pode converter um objeto no XML. A arquitetura é independente de qualquer formato de serialização específicas e também inclui uma implementação dessa arquitetura construída no modelo de objeto de documento da código (CodeDOM). |
Gerenciador de serialização |
Um Gerenciador de serialização é um objeto que fornece um armazenamento de informações para todos os serializadores diversas que são usados para serializar um gráfico de objeto.Um gráfico de 50 objetos pode ter 50 serializadores diferentes que todos geram seu próprios saída.O Gerenciador de serialização é usado por esses serializadores para se comunicar entre si. |
Os ilustração e o procedimento a seguir mostram como objetos em um gráfico, neste caso A e B, podem ser serializados.
Serialização de objetos em um gráfico
Chamador solicita um serializador para um objeto do Gerenciador de serialização:
MySerializer s = manager.GetSerializer(a);
Atributo de metadados na tipo vincula A um serializador do tipo solicitado.Chamador pede o serializador para serializar A:
Blob b = s.Serialize(manager, a);
Objeto do serializador serializa a.Para cada objeto ao serializar A encontrar, ele solicita serializadores adicionais do Gerenciador de serialização:
MySerializer s2 = manager.GetSerializer(b); Blob b2 = s2.Serialize(manager, b);
O resultado a serialização é retornado ao chamador:
Blob b = ...
Regras de serialização Geral
Um componente geralmente expõe várias propriedades.Por exemplo, o Windows Forms Button controle tem propriedades como BackColor, ForeColor, e BackgroundImage. Quando você coloca um Button controle em um formulário em um designer e você exibir o código gerado, você verá apenas um subconjunto das propriedades é mantido no código. Normalmente, essas são as propriedades para o qual você tiver definido explicitamente um valor.
The CodeDomSerializer associado com o Button o controle define o comportamento de serialização. A lista a seguir descreve algumas das regras usadas pelo CodeDomSerializer para serializar o valor de uma propriedade:
Se a propriedade tiver um DesignerSerializationVisibilityAttribute anexado a ele, o serializador usa isso para determinar se a propriedade é serializada (como Visible ou Hidden) e como serializar ()Content).
The Visible ou Hidden valores especificam se a propriedade é serializada. The Content o valor Especifica como a propriedade é serializada.
Para uma propriedade telefonar DemoProperty, se o componente implementa um método chamado ShouldSerializeDemoProperty, o ambiente de designer faz uma telefonar de ligação tardia para este método para determinar se a serializar. Por exemplo, para o BackColor propriedade, o método é chamado ShouldSerializeBackColor.
Se a propriedade tiver um DefaultValueAttribute o valor padrão especificado, será comparado com o valor corrente no componente. A propriedade é serializada apenas se o valor corrente for não-padrão.
O designer associado ao componente também pode executar uma parte em tomar a decisão de serialização por sombreamento propriedades ou implementando ShouldSerialize métodos propriamente dito.
Observação: |
---|
O serializador adia a decisão de serialização do PropertyDescriptor associada com a propriedade e PropertyDescriptor usa as regras listadas anteriormente. |
Se você deseja serializar seu componente de maneira diferente, você poderá escrever sua própria classe de serializador deriva de CodeDomSerializer e associar o componente usando o DesignerSerializerAttribute.
Implementação de serializador SMART
Um dos requisitos de design serializador é que, quando um novo formato de serialização é necessária, todos os tipos de dados devem ser atualizados com um atributo de metadados para oferecer suporte a esse formato.No entanto, por meio do uso de provedores de serialização juntamente com serializadores usam metadados de objeto genérico, esse requisito pode ser atendido.Esta seção descreve a melhor maneira de criar um serializador para um determinado formato para que a necessidade de muitos serializadores personalizados é minimizada.
O esquema a seguir define um formato XML hipotético ao qual um gráfico de objeto serão persistentes.
<TypeName>
<PropertyName>
ValueString
</PropertyName>
</TypeName>
Esse formato é serializado usando uma classe inventada chamada DemoXmlSerializer.
public abstract class DemoXmlSerializer
{
public abstract string Serialize(
IDesignerSerializationManager m,
object graph);
}
É importante entender que DemoXmlSerializer é uma classe modular cria uma seqüência de caracteres de peças. Por exemplo, a DemoXmlSerializer para o Int32 tipo de dados retornará a seqüência de caracteres de “ 23 ” quando passar um inteiro de valor 23.
Provedores de serialização
O exemplo de esquema anterior torna desmarcar que há dois tipos fundamentais deve ser tratado:
Objetos que possuem propriedades filho.
Objetos que podem ser convertidos em texto.
Seria difícil adornam todas as classes com um serializador personalizado que possa converter essa classe em texto ou as Rótulos XML.Provedores de serialização resolver isso, fornecendo um mecanismo de retorno de chamada na qual um objeto é terá a oportunidade de fornecer um serializador para um determinado tipo.Neste exemplo, o conjunto de tipos disponível é restrita pelas seguintes condições:
Se o tipo pode ser convertido em uma seqüência de caracteres usando o IConvertible interface, o StringXmlSerializer será usado.
Se o tipo não pode ser convertido em uma seqüência de caracteres, mas é pública e tem um construtor vazio, a ObjectXmlSerializer será usado.
Se nenhum deles for true, o provedor de serialização retornará null, indicando que não há nenhum serializador para o objeto.
O exemplo de código a seguir mostra como a chamada resolve serializador o que acontece com este erro ocorre.
internal class XmlSerializationProvider : IDesignerSerializationProvider
{
object GetSerializer(
IDesignerSerializationManager manager,
object currentSerializer,
Type objectType,
Type serializerType)
{
// Null values will be given a null type by this serializer.
// This test handles this case.
if (objectType == null)
{
return StringXmlSerializer.Instance;
}
if (typeof(IConvertible).IsSubclassOf(objectType))
{
return StringXmlSerializer.Instance;
}
if (objectType.GetConstructor(new object[]) != null)
{
return ObjectXmlSerializer.Instance;
}
return null;
}
}
Uma vez que um provedor de serialização é definido, ele deve ser colocado para usar.Um Gerenciador de serialização pode ser fornecido como um provedor de serialização através de AddSerializationProvider método, mas isso requer que esta telefonar sejam feitas para o Gerenciador de serialização. Um provedor de serialização pode ser adicionado automaticamente a um Gerenciador de serialização, adicionando um DefaultSerializationProviderAttribute para o serializador. Este atributo requer que o provedor de serialização tem um construtor público, vazio.O exemplo de código a seguir mostra a alterar necessária para DemoXmlSerializer.
[DefaultSerializationProvider(typeof(XmlSerializationProvider))]
public abstract class DemoXmlSerializer
{
}
Agora, sempre que um Gerenciador de serialização é solicitado para qualquer tipo de DemoXmlSerializer, o provedor de serialização padrão será adicionado ao Gerenciador de serialização se não tiver ocorrido já.
Serializadores
O exemplo DemoXmlSerializer classe tem duas classes concretas serializador chamados StringXmlSerializer e ObjectXmlSerializer. O exemplo de código a seguir mostra a implementação de StringXmlSerializer.
internal class StringXmlSerializer : DemoXmlSerializer
{
internal StringXmlSerializer Instance = new StringXmlSerializer();
public override string Serialize(
IDesignerSerializationManager m,
object graph)
{
if (graph == null) return string.Empty;
IConvertible c = graph as IConvertible;
if (c == null)
{
// Rather than throwing exceptions, add a list of errors
// to the serialization manager.
m.ReportError("Object is not IConvertible");
return null;
}
return c.ToString(CultureInfo.InvariantCulture);
}
}
The ObjectXmlSerializer implementação é mais atrativo, porque é necessário enumerar as propriedades públicas do objeto. O exemplo de código a seguir mostra a implementação de ObjectXmlSerializer.
internal class ObjectXmlSerializer : DemoXmlSerializer
{
internal ObjectXmlSerializer Instance = new ObjectXmlSerializer();
public override string Serialize(
IDesignerSerializationManager m,
object graph)
{
StringBuilder xml = new StringBuilder();
xml.Append(“<”);
xml.Append(graph.GetType().FullName);
xml.Append(“>”);
// Now, walk all the properties of the object.
PropertyDescriptorCollection properties;
Property p;
properties = TypeDescriptor.GetProperties(graph);
foreach(p in properties)
{
if (!p.ShouldSerializeValue(graph))
{
continue;
}
object value = p.GetValue(graph);
Type valueType = null;
if (value != null) valueType = value.GetType();
// Get the serializer for this property
DemoXmlSerializer s = m.GetSerializer(
valueType,
typeof(DemoXmlSerializer)) as DemoXmlSerializer;
if (s == null)
{
// Because there is no serializer,
// this property must be passed over.
// Tell the serialization manager
// of the error.
m.ReportError(string.Format(
“Property {0} does not support XML serialization”,
p.Name));
continue;
}
// You have a valid property to write.
xml.Append(“<”);
xml.Append(p.Name);
xml.Append(“>”);
xml.Append(s.Serialize(m, value);
xml.Append(“</”);
xml.Append(p.Name);
xml.Append(“>”);
}
xml.Append(“</”);
xml.Append(graph.GetType().FullName);
xml.Append(“>”);
return xml.ToString();
}
}
ObjectXmlSerializer chama outros serializadores para cada valor da propriedade. Isso tem duas vantagens.Primeiro, ele permite que ObjectXmlSerializer a ser muito simples. Segundo, ele fornece um ponto de extensibilidade para tipos de terceiros.If ObjectXmlSerializer é apresentada com um tipo que não pode ser gravado por qualquer um desses serializadores um serializador personalizado pode ser fornecido para o tipo.
Uso
Para usar esses novos serializadores, uma instância de IDesignerSerializationManager deve ser criado. Nesta instância, você pede um serializador e pedir o serializador para serializar seus objetos.Para obter o seguinte exemplo de código, Rectangle usada para um objeto serializado, porque esse tipo tem um construtor vazio e tem quatro propriedades que oferecem suporte IConvertible. Em vez de implementar IDesignerSerializationManager Você mesmo, você pode usar a implementação fornecida pelo DesignerSerializationManager.
Rectangle r = new Rectangle(5, 10, 15, 20);
DesignerSerializationManager m = new DesignerSerializationManager();
DemoXmlSerializer x = (DemoXmlSerializer)m.GetSerializer(
r.GetType(), typeof(DemoXmlSerializer);
string xml = x.Serialize(m, r);
Isso criaria o seguinte XML.
<System.Drawing.Rectangle>
<X>
5
</X>
<Y>
10
</Y>
<Width>
15
</Width>
<Height>
15
</Height>
</System.Drawing.Rectangle>
Observação: |
---|
O XML não é recuado.Isso poderia ser com com facilidade conseguido por meio do Context propriedade em IDesignerSerializationManager. Cada nível do serializador poderia adicionar um objeto para a pilha de contexto que contém o corrente nível de recuar e cada serializador poderia procurar desse objeto na pilha e usá-lo para fornecer um recuar. |
Consulte também
Referência
DefaultSerializationProviderAttribute