private static void WriteInterfaceDeclaration(FormattedTextWriter writer, SqlServerVersion version, ModelTypeClass type, string interfaceName, Element element)
 {
     writer.WriteLine();
     writer.WriteLine($"public interface {interfaceName} : {DacUtilities.BaseModelInterfaceFullName}");
     using (writer.StartBlock())
     {
         foreach (ModelPropertyClass property in GetProperties(type))
         {
             if (!DacUtilities.SupportsVersion(property.SupportedPlatforms, version))
             {
                 continue;
             }
             bool   useGenericGetter;
             string typeName     = GetPropertyTypeName(property.DataType, out useGenericGetter);
             string propertyName = GetPropertyName(property, element);
             writer.WriteLine();
             writer.WriteLine($"{typeName} {propertyName} {{ get; }}");
         }
     }
 }
        public static void GenerateVersionSpecificClasses(FormattedTextWriter writer)
        {
            writer.WriteFileHeader();
            writer.WriteLine($"namespace {DacUtilities.NamespaceName}");
            using (writer.StartBlock())
            {
                foreach (SqlServerVersion version in DacUtilities.GetSqlServerVersions())
                {
                    string interfacePrefix = GetInterfacePrefix(version);

                    foreach (ModelTypeClass type in ModelSchema.SchemaInstance.AllTypes)
                    {
                        string  interfaceName          = GetBaseInterfaceName(type, version);
                        string  referenceInterfaceName = GetReferenceInterfaceName(type, version);
                        Element element = DacUtilities.FindElement(type.Name);
                        if (element != null)
                        {
                            writer.WriteLine();
                            writer.WriteLine("/// <summary>");
                            writer.WriteLine($"/// Explicit implementation of <see cref=\"{interfaceName}\"/>.");
                            writer.WriteLine("/// </summary>");
                            writer.WriteLine($"public partial class {DacUtilities.ClassNamePrefix + type.Name} : {interfaceName}");
                            using (writer.StartBlock())
                            {
                                foreach (ModelPropertyClass property in GetProperties(type))
                                {
                                    if (!DacUtilities.SupportsVersion(property.SupportedPlatforms, version))
                                    {
                                        continue;
                                    }
                                    bool   useGenericGetter;
                                    string typeName     = GetPropertyTypeName(property.DataType, out useGenericGetter);
                                    string propertyName = GetPropertyName(property, element);
                                    writer.WriteLine();
                                    writer.WriteLine($"{typeName} {interfaceName}.{propertyName} => {propertyName};");
                                }
                                foreach (var relationship in type.Relationships.OrderBy(r => r.Name))
                                {
                                    if (!!DacUtilities.SupportsVersion(relationship.SupportedPlatforms, version))
                                    {
                                        continue;
                                    }
                                    string returnType     = DacUtilities.DefaultReturnType;
                                    string castExpression = "";
                                    if (element != null)
                                    {
                                        Relationship localoverride;
                                        if (element.Children.OfType <Relationship>().ToDictionary(r => r.Name, r => r).TryGetValue(relationship.Name, out localoverride))
                                        {
                                            if (localoverride.Specialize)
                                            {
                                                returnType     = $"{localoverride.ReturnTypeNamespace}.{interfacePrefix}{localoverride.ReturnType}";
                                                castExpression = $".Cast<{returnType}>()";
                                            }
                                            else
                                            {
                                                returnType = $"{localoverride.ReturnTypeNamespace}.{localoverride.ReturnType}";
                                            }
                                        }
                                    }
                                    writer.WriteLine();
                                    writer.WriteLine($"// {relationship.Type} relationship");
                                    writer.WriteLine($"{IEnumerableName}<{returnType}> {interfaceName}.{relationship.Name} => {relationship.Name + castExpression};");
                                }
                            }
                        }
                    }
                }
            }
        }