Example #1
0
 private static void Generate(INamedTypeSymbol typeToCreate, Compilation compilation, List <Service> services, KnownTypes knownTypes)
 {
     typeToCreate = (INamedTypeSymbol)typeToCreate.WithNullableAnnotation(default);
Example #2
0
        public static string Generate(Compilation compilation)
        {
            string stub = @"
namespace DI
{ 
    public static class ServiceLocator
    {
        public static T GetService<T>()
        {
            return default;
        }
    }
}
";

            var options = (compilation as CSharpCompilation)?.SyntaxTrees[0].Options as CSharpParseOptions;

            compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(stub, Encoding.UTF8), options));

            ImmutableArray <Diagnostic> diags = compilation.GetDiagnostics();

            var sourceBuilder = new StringBuilder();

            var services = new List <Service>();

            INamedTypeSymbol?serviceLocatorClass = compilation.GetTypeByMetadataName("DI.ServiceLocator") !;
            INamedTypeSymbol?transientAttribute  = compilation.GetTypeByMetadataName("Trains.NET.Engine.TransientAttribute") !;
            INamedTypeSymbol?orderAttribute      = compilation.GetTypeByMetadataName("Trains.NET.Engine.OrderAttribute") !;
            INamedTypeSymbol?layoutOfT           = compilation.GetTypeByMetadataName("Trains.NET.Engine.ILayout`1") !.ConstructUnboundGenericType();
            INamedTypeSymbol?filteredLayout      = compilation.GetTypeByMetadataName("Trains.NET.Engine.FilteredLayout`1") !;
            INamedTypeSymbol?iEnumerableOfT      = compilation.GetTypeByMetadataName("System.Collections.Generic.IEnumerable`1") !.ConstructUnboundGenericType();
            INamedTypeSymbol?listOfT             = compilation.GetTypeByMetadataName("System.Collections.Generic.List`1") !;

            var knownTypes = new KnownTypes(transientAttribute, orderAttribute, layoutOfT, filteredLayout, iEnumerableOfT, listOfT);

            foreach (SyntaxTree?tree in compilation.SyntaxTrees)
            {
                SemanticModel?semanticModel = compilation.GetSemanticModel(tree);
                IEnumerable <INamedTypeSymbol>?typesToCreate = from i in tree.GetRoot().DescendantNodesAndSelf().OfType <InvocationExpressionSyntax>()
                                                               let symbol = semanticModel.GetSymbolInfo(i).Symbol as IMethodSymbol
                                                                            where symbol != null
                                                                            where SymbolEqualityComparer.Default.Equals(symbol.ContainingType, serviceLocatorClass)
                                                                            select symbol.ReturnType as INamedTypeSymbol;

                foreach (INamedTypeSymbol?typeToCreate in typesToCreate)
                {
                    Generate(typeToCreate, compilation, services, knownTypes);
                }
            }

            sourceBuilder.AppendLine(@"
namespace DI
{ 
    public static class ServiceLocator
    {");
            var fields = new List <Service>();

            GenerateFields(sourceBuilder, services, fields);

            sourceBuilder.AppendLine(@"
        public static T GetService<T>()
        {");

            foreach (Service?service in services)
            {
                sourceBuilder.AppendLine("if (typeof(T) == typeof(" + service.Type + "))");
                sourceBuilder.AppendLine("{");
                sourceBuilder.AppendLine($"    return (T)(object){GetTypeConstruction(service, service.IsTransient ? new List<Service>() : fields)};");
                sourceBuilder.AppendLine("}");
            }

            sourceBuilder.AppendLine("throw new System.InvalidOperationException(\"Don't know how to initialize type: \" + typeof(T).Name);");
            sourceBuilder.AppendLine(@"
        }
    }
}");

            return(sourceBuilder.ToString());
        }
 private static void Generate(GeneratorExecutionContext context, INamedTypeSymbol typeToCreate, Compilation compilation, List <Service> services, Service?parent, KnownTypes knownTypes)
 {
     // System.Diagnostics.Debugger.Launch();
     typeToCreate = (INamedTypeSymbol)typeToCreate.WithNullableAnnotation(default);