Skip to content

Instantly share code, notes, and snippets.

@dadhi
Forked from danielcrenna/Demo.csproj
Last active May 8, 2020 05:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dadhi/3996ed1e760bff85c327407148db8864 to your computer and use it in GitHub Desktop.
Save dadhi/3996ed1e760bff85c327407148db8864 to your computer and use it in GitHub Desktop.
DI Source Generator
<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>
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) { }
}
}
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!");
}
}
}
<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