void t_netstd_generator::generate_netstd_struct_definition()

in compiler/cpp/src/thrift/generate/t_netstd_generator.cc [952:1170]


void t_netstd_generator::generate_netstd_struct_definition(ostream& out, t_struct* tstruct, bool is_exception, bool in_class, bool is_result)
{
    if (!in_class)
    {
        start_netstd_namespace(out);
    }

    out << '\n';

    generate_netstd_doc(out, tstruct);
    collect_extensions_types(tstruct);
    prepare_member_name_mapping(tstruct);

    if ((is_serialize_enabled() || is_wcf_enabled()) && !is_exception)
    {
        out << indent() << "[DataContract(Namespace=\"" << wcf_namespace_ << "\")]" << '\n';
    }

    bool is_final = tstruct->annotations_.find("final") != tstruct->annotations_.end();

    string sharp_struct_name = type_name(tstruct, false);

    generate_deprecation_attribute(out, tstruct->annotations_);
    out << indent() << "public " << (is_final ? "sealed " : "") << "partial class " << sharp_struct_name << " : ";

    if (is_exception)
    {
        out << "TException, ";
    }

    out << "TBase" << '\n'
        << indent() << "{" << '\n';
    indent_up();

    const vector<t_field*>& members = tstruct->get_members();
    vector<t_field*>::const_iterator m_iter;

    // make private members with public Properties
    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter)
    {
        // if the field is required, then we use auto-properties
        if (!field_is_required((*m_iter)))
        {
            out << indent() << "private " << declare_field(*m_iter, false, true, "_") << '\n';
        }
    }
    out << '\n';

    bool has_non_required_fields = false;
    bool has_required_fields = false;
    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter)
    {
        generate_netstd_doc(out, *m_iter);
        generate_property(out, *m_iter, true, true);
        bool is_required = field_is_required((*m_iter));
        if (is_required)
        {
            has_required_fields = true;
        }
        else
        {
            has_non_required_fields = true;
        }
    }

    bool generate_isset = has_non_required_fields;
    if (generate_isset)
    {
        out << '\n';
        if (is_serialize_enabled() || is_wcf_enabled())
        {
            out << indent() << "[DataMember(Order = 1)]" << '\n';
        }
        out << indent() << "public Isset __isset;" << '\n';
        if (is_serialize_enabled() || is_wcf_enabled())
        {
            out << indent() << "[DataContract]" << '\n';
        }

        out << indent() << "public struct Isset" << '\n'
            << indent() << "{" << '\n';
        indent_up();

        for (m_iter = members.begin(); m_iter != members.end(); ++m_iter)
        {
            bool is_required = field_is_required((*m_iter));
            // if it is required, don't need Isset for that variable
            // if it is not required, if it has a default value, we need to generate Isset
            if (!is_required)
            {
                if (is_serialize_enabled() || is_wcf_enabled())
                {
                    out << indent() << "[DataMember]" << '\n';
                }
                out << indent() << "public bool " << get_isset_name(normalize_name((*m_iter)->get_name())) << ";" << '\n';
            }
        }

        indent_down();
        out << indent() << "}" << '\n' << '\n';

        if (generate_isset && (is_serialize_enabled() || is_wcf_enabled()))
        {
            out << indent() << "#region XmlSerializer support" << '\n' << '\n';

            for (m_iter = members.begin(); m_iter != members.end(); ++m_iter)
            {
                bool is_required = field_is_required(*m_iter);
                // if it is required, don't need Isset for that variable
                // if it is not required, if it has a default value, we need to generate Isset
                if (!is_required)
                {
                    out << indent() << "public bool ShouldSerialize" << prop_name(*m_iter) << "()" << '\n'
                        << indent() << "{" << '\n';
                    indent_up();
                    out << indent() << "return __isset." << get_isset_name(normalize_name((*m_iter)->get_name())) << ";" << '\n';
                    indent_down();
                    out << indent() << "}" << '\n' << '\n';
                }
            }

            out << indent() << "#endregion XmlSerializer support" << '\n' << '\n';
        }
    }

    // We always want a default, no argument constructor for Reading
    out << indent() << "public " << sharp_struct_name << "()" << '\n'
        << indent() << "{" << '\n';
    indent_up();

    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter)
    {
        t_type* t = (*m_iter)->get_type();
        t = resolve_typedef(t);

        if ((*m_iter)->get_value() != nullptr)
        {
            if (field_is_required((*m_iter)))
            {
                print_const_value(out, "this." + normalize_name(prop_name(*m_iter)), t, (*m_iter)->get_value(), true, true);
            }
            else
            {
                print_const_value(out, "this._" + (*m_iter)->get_name(), t, (*m_iter)->get_value(), true, true);
                // Optionals with defaults are marked set
                out << indent() << "this.__isset." << get_isset_name(normalize_name((*m_iter)->get_name())) << " = true;" << '\n';
            }
        }
    }
    indent_down();
    out << indent() << "}" << '\n' << '\n';

    // if we have required fields, we add that CTOR too
    if (has_required_fields)
    {
        out << indent() << "public " << sharp_struct_name << "(";
        bool first = true;
        for (m_iter = members.begin(); m_iter != members.end(); ++m_iter)
        {
            if (field_is_required(*m_iter))
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    out << ", ";
                }
                out << type_name((*m_iter)->get_type()) << nullable_field_suffix(*m_iter) << " " << normalize_name((*m_iter)->get_name());
            }
        }
        out << ") : this()" << '\n'
            << indent() << "{" << '\n';
        indent_up();

        for (m_iter = members.begin(); m_iter != members.end(); ++m_iter)
        {
            if (field_is_required(*m_iter))
            {
                out << indent() << "this." << prop_name(*m_iter) << " = " << normalize_name((*m_iter)->get_name()) << ";" << '\n';
            }
        }

        indent_down();
        out << indent() << "}" << '\n' << '\n';
    }

    // DeepCopy()
    generate_netstd_deepcopy_method(out, tstruct, sharp_struct_name);

    generate_netstd_struct_reader(out, tstruct);
    if (is_result)
    {
        generate_netstd_struct_result_writer(out, tstruct);
    }
    else
    {
        generate_netstd_struct_writer(out, tstruct);
    }
    generate_netstd_struct_equals(out, tstruct);
    generate_netstd_struct_hashcode(out, tstruct);
    generate_netstd_struct_tostring(out, tstruct);

    indent_down();
    out << indent() << "}" << '\n' << '\n';

    // generate a corresponding WCF fault to wrap the exception
    if ((is_serialize_enabled() || is_wcf_enabled()) && is_exception)
    {
        generate_netstd_wcffault(out, tstruct);
    }

    cleanup_member_name_mapping(tstruct);
    if (!in_class)
    {
        end_netstd_namespace(out);
    }
}