Example #1
0
        private void EmitOverridenNavigationProperties(StringBuilder builder, INamedTypeSymbol type)
        {
            //TODO: Support ALL foreign key scenarios. Right now only traditional attribute-based PropId and Prop pair scenarios are supported
            //Find all foreign key references and generate
            //the required overrides for their navigation properties.
            foreach (var prop in type
                     .GetMembers()
                     .Where(m => m.HasAttributeLike <ForeignKeyAttribute>() || m.HasAttributeExact <CompositeKeyHintAttribute>())
                     .Cast <IPropertySymbol>())
            {
                //Special handling for composite key table references
                if (prop.Type.HasAttributeExact <CompositeKeyHintAttribute>() && prop.HasAttributeLike <CompositeKeyHintAttribute>())
                {
                    //TODO: Hack to get the key name
                    //TODO: Is it ok for open generics to use the type args??
                    string keyTypeName   = ComputeCompositeKeyTypeName(prop);
                    string keyResolution = new TablePrimaryKeyParser().BuildCompositeKeyCreationExpression(prop, "base", keyTypeName);

                    builder.Append($"[{nameof(IgnoreDataMemberAttribute)}]{Environment.NewLine}");
                    builder.Append($"public override {prop.Type.ToFullName()} {prop.Name} {Environment.NewLine}{{ get => {OriginalContextSymbol.GetFriendlyName()}.Instance.{new TableNameParser().Parse(prop.Type)}[{keyResolution}];{Environment.NewLine}");

                    builder.Append($"}}{Environment.NewLine}");
                }
                else
                {
                    IPropertySymbol navProperty = RetrieveNavigationPropertySymbol(prop);
                    IPropertySymbol keyProperty = RetrieveNavigationKeyPropertySymbol(prop);

                    builder.Append($"[{nameof(IgnoreDataMemberAttribute)}]{Environment.NewLine}");
                    builder.Append($"public override {navProperty.Type.ToFullName()} {navProperty.Name} {Environment.NewLine}{{ get => {OriginalContextSymbol.GetFriendlyName()}.Instance.{new TableNameParser().Parse(navProperty.Type)}[base.{keyProperty.Name}];{Environment.NewLine}");

                    builder.Append($"}}{Environment.NewLine}");
                }
            }
        }
Example #2
0
        private void EmitSerializableInitializeMethod(StringBuilder builder)
        {
            builder.Append($"{Environment.NewLine}");
            builder.Append($"public void {nameof(IGGDBFSerializable.Initialize)}({nameof(IGGDBFDataConverter)} converter){Environment.NewLine}{{{Environment.NewLine}");

            foreach (var prop in EnumerateForeignCollectionProperties())
            {
                string           fieldName             = ComputeCollectionPropertyBackingFieldName(prop);
                INamedTypeSymbol collectionElementType = (INamedTypeSymbol)ComputeCollectionElementType(prop);

                //TODO: Hack to get the key name
                //TODO: Is it ok for open generics to use the type args??
                string keyTypeName         = CreateKeyTypeForCollectionType(collectionElementType);
                string keyResolutionLambda = new TablePrimaryKeyParser().BuildKeyResolutionLambda(collectionElementType, keyTypeName);

                builder.Append($"{fieldName} = {nameof(GGDBFHelpers)}.{nameof(GGDBFHelpers.CreateSerializableCollection)}({keyResolutionLambda}, {prop.Name});{Environment.NewLine}");
            }

            foreach (var prop in EnumerateOwnedTypeForeignCollectionProperties())
            {
                string           fieldName             = ComputeCollectionPropertyBackingFieldName(prop);
                INamedTypeSymbol collectionElementType = (INamedTypeSymbol)ComputeCollectionElementType(prop);

                builder.Append($"{fieldName} = converter.{nameof(IGGDBFDataConverter.Convert)}<{collectionElementType.ToFullName()}, {ComputeOwnedTypeName(collectionElementType)}>({prop.Name});{Environment.NewLine}");
            }

            builder.Append($"}}");
        }
Example #3
0
        private void EmitModelKeyTypeSource(INamedTypeSymbol contextSymbol, GeneratorExecutionContext context, INamedTypeSymbol type)
        {
            string keyName = new TablePrimaryKeyParser().ParseSimple(type);

            StringBuilder             builder            = new StringBuilder();
            UsingsEmitter             usingsEmitter      = new();
            NamespaceDecoratorEmitter namespaceDecorator = new NamespaceDecoratorEmitter(new CompositeKeyTypeEmitter(keyName, type, Accessibility.Public), contextSymbol.ContainingNamespace.FullNamespaceString());

            //If the type is another namespace we should import it
            //so we don't have to use fullnames.
            AddNamespacesForType(type, usingsEmitter);

            usingsEmitter.AddNamespaces(GGDBFConstants.DEFAULT_NAMESPACES);

            usingsEmitter.Emit(builder);
            namespaceDecorator.Emit(builder);

            string source     = builder.ToString();
            string hashMapKey = $"{keyName} {source.Substring(source.IndexOf('{'))}";

            //Keys could be shared in cases of multiple contexts
            if (EmittedKeyTypes.Contains(hashMapKey))
            {
                return;
            }

            EmittedKeyTypes.Add(hashMapKey);
            context.AddSource($"{contextSymbol.Name}_{keyName}", ConvertFileToNode(context, builder).ToString());
        }