/// <summary>
        /// Adicionar um objeto do tipo RegistroBaseSped no atributo "Linhas".
        /// Caso existe alguma falha na geração, adiciona a falha no atributo "Erros"
        /// </summary>
        protected void EscreverLinha(RegistroBaseSped registro)
        {
            string erro;
            string texto = registro.EscreverCampos(out erro, null, true);

            if (!string.IsNullOrEmpty(erro))
            {
                Erros.Add(erro);
            }

            Linhas.Add(texto);
        }
        /// <summary>
        /// Escrever campos p/ qualquer arquivo do projeto SPED (Contábil, Fiscal, Pis/Cofins)
        /// </summary>
        /// <param name="source">Objeto com os dados a serem tratados e gerados na linha do arquivo.</param>
        /// <param name="competenciaDeclaracao">Mês a que se referem as informações no arquivo(exceto informações extemporâneas).</param>
        /// <param name="errosEncontrados">Lista com erros encontrados no processo de escrita.</param>
        /// <param name="tryTrim">Remove a quebra de linha no final de cada registro.</param>
        /// <returns>Linha de arquivo SPED escrita e formatada.</returns>
        public static string EscreverCampos(this object source, out string errosEncontrados,
                                            DateTime?competenciaDeclaracao = null, bool tryTrim = false)
        {
            errosEncontrados = string.Empty;

            var type = ObtemTipo(source);

            var registroAtual = ObtemRegistroAtual(type);

            var spedRegistroAttr = ObtemAtributoAtual(type);

            var dataObrigatoriedadeInicial = spedRegistroAttr != null?spedRegistroAttr.ObrigatoriedadeInicial.ToDateTimeNullable() : null;

            var dataObrigatoriedadeFinal = spedRegistroAttr != null?spedRegistroAttr.ObrigatoriedadeFinal.ToDateTimeNullable() : null;

            if (!competenciaDeclaracao.HasValue)
            {
                competenciaDeclaracao = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
            }
            else
            {
                competenciaDeclaracao = new DateTime(competenciaDeclaracao.Value.Year, competenciaDeclaracao.Value.Month, 1);
            }

            var deveGerarCamposDoRegistro =
                VerificaObrigatoriedadeRegistro(new Tuple <DateTime?, DateTime?, DateTime>(dataObrigatoriedadeInicial,
                                                                                           dataObrigatoriedadeFinal, competenciaDeclaracao.Value));

            var listaComPropriedadesOrdenadas = ObtemListaComPropriedadesOrdenadas(type);

            var sb = new StringBuilder();

            if (deveGerarCamposDoRegistro)
            {
                foreach (var property in listaComPropriedadesOrdenadas)
                {
                    if (SomenteParaLeitura(property))
                    {
                        continue;
                    }

                    sb.Append("|");
                    foreach (
                        var spedCampoAttr in
                        from Attribute attr in property.GetCustomAttributes(true) select attr as SpedCamposAttribute
                        )
                    {
                        if (spedCampoAttr == null)
                        {
                            errosEncontrados +=
                                string.Format("O campo {0} no registro {1} não possui atributo SPED definido!\n", property.Name, registroAtual);
                        }

                        var propertyValue             = RegistroBaseSped.GetPropValue(source, property.Name);
                        var propertyValueToStringSafe = propertyValue.ToStringSafe().Trim();

                        var isRequired            = spedCampoAttr.IsObrigatorio;
                        var resultadoCampoEscrito =
                            propertyValueToStringSafe.EscreverCampo(
                                new Tuple <
                                    InformationType,
                                    InformationType,
                                    bool,
                                    int,
                                    int>(
                                    ObtemTipoDoAtributo(spedCampoAttr),
                                    ObtemTipoDaPropriedade(property),
                                    isRequired,
                                    spedCampoAttr.Tamanho,
                                    spedCampoAttr.QtdCasas
                                    ));

                        if (resultadoCampoEscrito == Constantes.StructuralError)
                        {
                            errosEncontrados +=
                                string.Format("O campo {0} - {1} no Registro {2} é obrigatório e não foi informado!\n", spedCampoAttr.Ordem, spedCampoAttr.Campo, registroAtual);
                        }
                        else
                        {
                            sb.Append(resultadoCampoEscrito);
                        }
                    }
                }
                sb.Append("|");
                sb.Append(Environment.NewLine);
            }
            if (errosEncontrados.Length > 0)
            {
                errosEncontrados =
                    string.Format("Registro {0} -  Contém os seguintes erros: \n{1}", source.GetType().FullName, errosEncontrados);
            }
            return(tryTrim ? sb.ToString().Trim() : sb.ToString());
        }