private static void Generate(INamedTypeSymbol typeToCreate, Compilation compilation, List <Service> services, KnownTypes knownTypes) { typeToCreate = (INamedTypeSymbol)typeToCreate.WithNullableAnnotation(default);
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);