public void Generate()
        {
            //Find all serializable types that are serializable from/to
            INamedTypeSymbol[] serializableTypes = TargetAssembly
                                                   .Where(IsSerializableType)
                                                   .ToArray();

            foreach (INamedTypeSymbol type in serializableTypes)
            {
                //THIS SHOULD NEVER HAPPEN!
                //if (type.IsGenericType && !type.IsUnboundGenericType)
                //	throw new InvalidOperationException($"Encountered unbound generic Type: {type.Name} in top-level search.");

                //This is for GENERIC types.
                //We can only realistically support closed generic forward declared types
                //AND also primitive generic type support.
                if (type.IsGenericType)
                {
                    if (type.HasAttributeExact <PrimitiveGenericAttribute>())
                    {
                        foreach (Type[] gta in PrimitiveGenericAttribute.Instance
                                 .Permutations(type.Arity)
                                 .Select(em => em.ToArray())
                                 .ToArray())
                        {
                            //Represents an array of type arguments for symbols
                            ITypeSymbol[] genericTypeArgSymbols = gta.Select(t => CompilationUnit.GetTypeByMetadataName(t.FullName))
                                                                  .Cast <ITypeSymbol>()
                                                                  .ToArray();

                            INamedTypeSymbol boundGenericType = type.Construct(genericTypeArgSymbols);
                            WriteSerializerStrategyClass(boundGenericType);
                        }
                    }

                    //If it's marked with KnownGeneric attribute then we should generate
                    //a serializer for each closed generic type.
                    if (type.HasAttributeExact <KnownGenericAttribute>())
                    {
                        foreach (AttributeData data in type.GetAttributesExact <KnownGenericAttribute>())
                        {
                            //Skip, this is include attribute. Maybe warn?
                            if (data.ConstructorArguments.IsDefaultOrEmpty)
                            {
                                continue;
                            }

                            //TODO: Does this work? Arrays may work different with API
                            //create types for each tuple of generic attributes
                            INamedTypeSymbol boundGenericType = type.Construct(data.ConstructorArguments.First().Values.Select(v => v.Value).Cast <ITypeSymbol>().ToArray());
                            WriteSerializerStrategyClass(boundGenericType);
                        }
                    }

                    if (type.HasAttributeExact <ClosedGenericAttribute>())
                    {
                        foreach (AttributeData closedTypeAttri in type.GetAttributesExact <ClosedGenericAttribute>())
                        {
                            WriteSerializerStrategyClass((INamedTypeSymbol)closedTypeAttri.ConstructorArguments.First().Value);
                        }
                    }

#warning TODO: Reimplement BaseGenericListAttribute support
                    //To support custom generic lists we created this open-ended base attribute
                    //and we just create combinations from it.

                    /*foreach (BaseGenericListAttribute genericAttri in type.GetCustomAttributes<BaseGenericListAttribute>())
                     * {
                     *      //Iterate the generic type list and we can build.
                     *      //closed generic types for all variants
                     *      foreach(IEnumerable<Type> genericParameterList in genericAttri.Permutations(type.GetGenericParameterCount()))
                     *              WriteSerializerStrategyClass(type.MakeGenericType(genericParameterList.ToArray()));
                     * }*/
                }
                else
                {
                    WriteSerializerStrategyClass(type);
                }
            }

            //It's important that we dynamically emit generic serializers
            //if none are found in refences or soon-to-be emitted serializers

            //copy because something will modify this array and then we need to continue until it's empty
            //because we could have an object graph that goes deep into multiple generics.
            int genericDepth = 0;
            do
            {
                ITypeSymbol[] genericTypeSymbols = RequiredGenericSerializers.ToArray();
                RequiredGenericSerializers.Clear();
                EmitRequestedGenericTypeSerializers(genericTypeSymbols);
                genericDepth++;

                //This loop is kinda dangerous, but we assume it'll eventually terminate.
            } while (RequiredGenericSerializers.Any() && genericDepth < 10);

            if (genericDepth >= 10)
            {
                throw new InvalidOperationException($"Automatic generic type serialization depth exceed maximum depth.");
            }
        }