Last active
May 10, 2020 14:59
-
-
Save danielcrenna/8bf8a23f3ad03f7985838ce5c7e31542 to your computer and use it in GitHub Desktop.
DI Source Generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>net5.0</TargetFramework> | |
<LangVersion>preview</LangVersion> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.0-preview.3.20215.2" /> | |
</ItemGroup> | |
<ItemGroup> | |
<ProjectReference Include="..\SourceGenerators\SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> | |
</ItemGroup> | |
</Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Text; | |
using System.Linq; | |
using Microsoft.CodeAnalysis; | |
using Microsoft.CodeAnalysis.CSharp.Syntax; | |
using Microsoft.CodeAnalysis.Text; | |
using Microsoft.Extensions.DependencyInjection; | |
namespace SourceGenerators | |
{ | |
[Generator] | |
public class DependencyInjectionGenerator : ISourceGenerator | |
{ | |
public void Execute(SourceGeneratorContext context) | |
{ | |
var body = new StringBuilder(@" | |
using System; | |
namespace Generated | |
{ | |
public static class DependencyResolver | |
{ | |
"); | |
var usings = new HashSet<string>(); | |
var syntaxTrees = context.Compilation.SyntaxTrees; | |
foreach (SyntaxTree tree in syntaxTrees) | |
{ | |
var nodes = tree.GetRoot().DescendantNodes(); | |
var model = context.Compilation.GetSemanticModel(tree); | |
IEnumerable<InvocationExpressionSyntax> invocations = nodes.OfType<InvocationExpressionSyntax>(); | |
foreach (var invocation in invocations) | |
{ | |
if (model.GetSymbolInfo(invocation.Expression).Symbol is IMethodSymbol method) | |
{ | |
if (method.Name == nameof(ServiceCollectionServiceExtensions.AddTransient)) | |
{ | |
// | |
// .AddTransient<ContractType, ImplementationType>(); | |
// | |
if (method.TypeArguments.Length == 2) | |
{ | |
var contract = method.TypeArguments[0]; | |
var concrete = method.TypeArguments[1]; | |
usings.Add(contract.ContainingNamespace.Name); | |
usings.Add(concrete.ContainingNamespace.Name); | |
body.AppendLine($"public static {contract.ContainingNamespace.Name}.{contract.Name} Resolve<{contract.Name}>() "); | |
body.AppendLine("{"); | |
body.AppendLine($" return new {concrete.ContainingNamespace.Name}.{concrete.Name}();"); | |
body.AppendLine("}"); | |
} | |
} | |
} | |
} | |
} | |
body.Append(@" | |
} // DependencyResolver | |
} // Generated"); | |
var code = new StringBuilder(); | |
foreach (var @using in usings) | |
code.AppendLine($"using {@using};"); | |
code.AppendLine(body.ToString()); | |
context.AddSource(nameof(DependencyInjectionGenerator), SourceText.From(code.ToString(), Encoding.UTF8)); | |
} | |
public void Initialize(InitializationContext context) { } | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Microsoft.Extensions.DependencyInjection; | |
namespace Demo | |
{ | |
static class Program | |
{ | |
static void Main(string[] args) | |
{ | |
IFoo foo = Generated.DependencyResolver.Resolve<IFoo>(); | |
foo.Bar(); | |
} | |
static void Dependencies(this IServiceCollection services) | |
{ | |
services.AddTransient<IFoo, Foo>(); | |
} | |
} | |
public interface IFoo | |
{ | |
void Bar(); | |
} | |
public class Foo : IFoo | |
{ | |
public void Bar() | |
{ | |
Console.WriteLine("Bar!"); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<TargetFramework>netstandard2.0</TargetFramework> | |
<LangVersion>preview</LangVersion> | |
</PropertyGroup> | |
<PropertyGroup> | |
<RestoreAdditionalProjectSources>https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json ;$(RestoreAdditionalProjectSources)</RestoreAdditionalProjectSources> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.6.0-3.20207.2" PrivateAssets="all" /> | |
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.0.0-beta2.final" PrivateAssets="all" /> | |
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.0-preview.3.20215.2" /> | |
</ItemGroup> | |
</Project> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment