diff --git a/Biwen.AutoClassGen.Attributes/AutoInjectAttribute.cs b/Biwen.AutoClassGen.Attributes/AutoInjectAttribute.cs
new file mode 100644
index 0000000..eaf476a
--- /dev/null
+++ b/Biwen.AutoClassGen.Attributes/AutoInjectAttribute.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace Biwen.AutoClassGen.Attributes
+{
+#if NET7_0_OR_GREATER
+
+ ///
+ /// 服务生命周期
+ ///
+ public enum ServiceLifetime
+ {
+ Singleton = 1,
+ Transient = 2,
+ Scoped = 4,
+ }
+
+
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class AutoInjectAttribute : Attribute
+ {
+ public ServiceLifetime ServiceLifetime { get; set; }
+
+ public AutoInjectAttribute(ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
+ {
+ ServiceLifetime = serviceLifetime;
+ }
+ }
+
+#endif
+
+}
\ No newline at end of file
diff --git a/Biwen.AutoClassGen.Gen/AutoInjectSourceGenerator.cs b/Biwen.AutoClassGen.Gen/AutoInjectSourceGenerator.cs
new file mode 100644
index 0000000..3a1217f
--- /dev/null
+++ b/Biwen.AutoClassGen.Gen/AutoInjectSourceGenerator.cs
@@ -0,0 +1,216 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Text;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Text;
+
+namespace Biwen.AutoClassGen
+{
+ [Generator(LanguageNames.CSharp)]
+ public class AutoInjectSourceGenerator : IIncrementalGenerator
+ {
+ private const string AttributeValueMetadataNameInject = "AutoInject";
+
+ ///
+ /// 泛型AutoInjectAttribute
+ ///
+ private const string GenericAutoInjectAttributeName = "Biwen.AutoClassGen.Attributes.AutoInjectAttribute`1";
+
+
+ public void Initialize(IncrementalGeneratorInitializationContext context)
+ {
+ var nodesDtoG = context.SyntaxProvider.ForAttributeWithMetadataName(
+ GenericAutoInjectAttributeName,
+ (context, attributeSyntax) => true,
+ (syntaxContext, _) => syntaxContext.TargetNode).Collect();
+
+ IncrementalValueProvider<(Compilation, ImmutableArray)> compilationAndTypesInjectG =
+ context.CompilationProvider.Combine(nodesDtoG);
+
+ context.RegisterSourceOutput(compilationAndTypesInjectG, static (spc, source) => HandleGenericAnnotatedNodesInject(source.Item1, source.Item2, spc));
+ }
+
+ ///
+ /// Gen AutoInjectAttribute G
+ ///
+ ///
+ ///
+ ///
+ private static void HandleGenericAnnotatedNodesInject(Compilation compilation, ImmutableArray nodes, SourceProductionContext context)
+ {
+ if (nodes.Length == 0) return;
+
+ // 注册的服务
+ List autoInjects = [];
+ List namespaces = [];
+
+ foreach (ClassDeclarationSyntax node in nodes.AsEnumerable().Cast())
+ {
+ AttributeSyntax? attributeSyntax = null;
+ foreach (var attr in node.AttributeLists.AsEnumerable())
+ {
+ var attrName = attr.Attributes.FirstOrDefault()?.Name.ToString();
+
+ attributeSyntax = attr.Attributes.First(x => x.Name.ToString().IndexOf(AttributeValueMetadataNameInject, System.StringComparison.Ordinal) == 0);
+
+ if (attrName?.IndexOf(AttributeValueMetadataNameInject, System.StringComparison.Ordinal) == 0)
+ {
+ //转译的Entity类名
+ var baseTypeName = string.Empty;
+
+ string pattern = @"(?<=<)(?\w+)(?=>)";
+ var match = Regex.Match(attributeSyntax.ToString(), pattern);
+ if (match.Success)
+ {
+ baseTypeName = match.Groups["type"].Value.Split(['.']).Last();
+ }
+ else
+ {
+ continue;
+ }
+
+ var implTypeName = node.Identifier.ValueText;
+ var rootNamespace = node.AncestorsAndSelf().OfType().Single().Name.ToString();
+
+ var symbols = compilation.GetSymbolsWithName(implTypeName);
+ foreach (ITypeSymbol symbol in symbols.Cast())
+ {
+ var fullNameSpace = symbol.ContainingNamespace.ToDisplayString();
+ // 命名空间
+ if (!namespaces.Contains(fullNameSpace))
+ {
+ namespaces.Add(fullNameSpace);
+ }
+ }
+
+ string lifeTime = "AddScoped";
+ {
+ if (attributeSyntax.ArgumentList != null)
+ {
+ for (var i = 0; i < attributeSyntax.ArgumentList!.Arguments.Count; i++)
+ {
+ var expressionSyntax = attributeSyntax.ArgumentList.Arguments[i].Expression;
+ if (expressionSyntax.IsKind(SyntaxKind.SimpleMemberAccessExpression))
+ {
+ var name = (expressionSyntax as MemberAccessExpressionSyntax)!.Name.Identifier.ValueText;
+ lifeTime = name switch
+ {
+ "Singleton" => "AddSingleton",
+ "Transient" => "AddTransient",
+ "Scoped" => "AddScoped",
+ _ => "AddScoped",
+ };
+ break;
+ }
+ }
+ }
+
+ autoInjects.Add(new AutoInjectDefine
+ {
+ ImplType = implTypeName,
+ BaseType = baseTypeName,
+ LifeTime = lifeTime,
+ });
+
+ //命名空间
+ symbols = compilation.GetSymbolsWithName(baseTypeName);
+ foreach (ITypeSymbol symbol in symbols.Cast())
+ {
+ var fullNameSpace = symbol.ContainingNamespace.ToDisplayString();
+ // 命名空间
+ if (!namespaces.Contains(fullNameSpace))
+ {
+ namespaces.Add(fullNameSpace);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // 生成代码
+ StringBuilder classes = new();
+ foreach (var define in autoInjects)
+ {
+ if (define.ImplType != define.BaseType)
+ {
+ classes.AppendLine($@"services.{define.LifeTime}<{define.BaseType}, {define.ImplType}>();");
+ }
+ else
+ {
+ classes.AppendLine($@"services.{define.LifeTime}<{define.ImplType}>();");
+ }
+ }
+
+ string rawNamespace = string.Empty;
+ namespaces.ForEach(ns => rawNamespace += $"using {ns};\r\n");
+
+ var envSource = Template.Replace("$services", classes.ToString());
+ envSource = envSource.Replace("$namespaces", rawNamespace);
+ // format:
+ envSource = FormatContent(envSource);
+ context.AddSource($"Biwen.AutoClassGenInjectG.g.cs", SourceText.From(envSource, Encoding.UTF8));
+ }
+
+ private class AutoInjectDefine
+ {
+ public string ImplType { get; set; } = null!;
+ public string BaseType { get; set; } = null!;
+
+ public string LifeTime { get; set; } = null!;
+ }
+
+
+ #region tmpl
+
+ private const string Template = """
+ //
+ // author:vipwan@outlook.com 万雅虎
+ // issue:https://github.com/vipwan/Biwen.AutoClassGen/issues
+ // 如果你在使用中遇到问题,请第一时间issue,谢谢!
+ // This file is generated by Biwen.AutoClassGen.AutoInjectSourceGenerator
+
+ #pragma warning disable
+ namespace Microsoft.Extensions.DependencyInjection
+ {
+ $namespaces
+
+ public static class ServiceCollectionExtension
+ {
+ ///
+ /// 自动注册标注的服务
+ ///
+ ///
+ ///
+ public static IServiceCollection AddAutoInject(this IServiceCollection services)
+ {
+ $services
+ return services;
+ }
+ }
+ }
+ #pragma warning restore
+ """;
+
+ #endregion
+
+
+ ///
+ /// 格式化代码
+ ///
+ ///
+ ///
+ private static string FormatContent(string csCode)
+ {
+ var tree = CSharpSyntaxTree.ParseText(csCode);
+ var root = tree.GetRoot().NormalizeWhitespace();
+ var ret = root.ToFullString();
+ return ret;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Biwen.AutoClassGen.TestConsole/Biwen.AutoClassGen.TestConsole.csproj b/Biwen.AutoClassGen.TestConsole/Biwen.AutoClassGen.TestConsole.csproj
index 2c070df..5ad4e8a 100644
--- a/Biwen.AutoClassGen.TestConsole/Biwen.AutoClassGen.TestConsole.csproj
+++ b/Biwen.AutoClassGen.TestConsole/Biwen.AutoClassGen.TestConsole.csproj
@@ -1,4 +1,4 @@
-
+
Exe
@@ -15,4 +15,5 @@
+
diff --git a/Biwen.AutoClassGen.TestConsole/Program.cs b/Biwen.AutoClassGen.TestConsole/Program.cs
index cf60db4..0abd6dc 100644
--- a/Biwen.AutoClassGen.TestConsole/Program.cs
+++ b/Biwen.AutoClassGen.TestConsole/Program.cs
@@ -16,6 +16,10 @@
// add auto decor
builder.Services.AddAutoDecor();
+
+builder.Services.AddAutoInject();
+
+
var app = builder.Build();
diff --git a/Biwen.AutoClassGen.TestConsole/Services/ServiceCollectionExtension.cs b/Biwen.AutoClassGen.TestConsole/Services/ServiceCollectionExtension.cs
new file mode 100644
index 0000000..f543d13
--- /dev/null
+++ b/Biwen.AutoClassGen.TestConsole/Services/ServiceCollectionExtension.cs
@@ -0,0 +1,27 @@
+////
+//// author:vipwan@outlook.com 万雅虎
+//// issue:https://github.com/vipwan/Biwen.AutoClassGen/issues
+//// 如果你在使用中遇到问题,请第一时间issue,谢谢!
+//// This file is generated by Biwen.AutoClassGen.AutoInjectSourceGenerator
+//#pragma warning disable
+//namespace Microsoft.Extensions.DependencyInjection1
+//{
+// using Biwen.AutoClassGen.TestConsole.Services;
+
+// public static class ServiceCollectionExtension
+// {
+// ///
+// /// 自动注册标注的服务
+// ///
+// ///
+// ///
+// public static IServiceCollection AddAutoInjectX(this IServiceCollection services)
+// {
+// services.AddScoped();
+// services.AddSingleton();
+// services.AddScoped();
+// return services;
+// }
+// }
+//}
+//#pragma warning restore
diff --git a/Biwen.AutoClassGen.TestConsole/Services/TestService.cs b/Biwen.AutoClassGen.TestConsole/Services/TestService.cs
new file mode 100644
index 0000000..2eaa112
--- /dev/null
+++ b/Biwen.AutoClassGen.TestConsole/Services/TestService.cs
@@ -0,0 +1,31 @@
+namespace Biwen.AutoClassGen.TestConsole.Services
+{
+
+ using Biwen.AutoClassGen.Attributes;
+
+ public interface ITestService
+ {
+ string Say(string message);
+ }
+
+ public interface ITest2Service
+ {
+ string Say2(string message);
+ }
+
+ [AutoInject]
+ [AutoInject(ServiceLifetime.Singleton)]
+ [AutoInject(ServiceLifetime.Scoped)]
+ public class TestService : ITestService, ITest2Service
+ {
+ public string Say(string message)
+ {
+ return $"hello {message}";
+ }
+
+ public string Say2(string message)
+ {
+ return message;
+ }
+ }
+}
\ No newline at end of file