diff --git a/build/version.props b/build/version.props
index 71824219..dacf3585 100644
--- a/build/version.props
+++ b/build/version.props
@@ -1,7 +1,7 @@
- 0
- 7
+ 1
+ 0
0
$(VersionMajor).$(VersionMinor).$(VersionPatch)
diff --git a/configuration/AspectCore.Extensions.Configuration.sln b/configuration/AspectCore.Extensions.Configuration.sln
new file mode 100644
index 00000000..d57a4ccd
--- /dev/null
+++ b/configuration/AspectCore.Extensions.Configuration.sln
@@ -0,0 +1,53 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspectCore.Extensions.Configuration", "src\AspectCore.Extensions.Configuration\AspectCore.Extensions.Configuration.csproj", "{F031B41A-C7D1-475C-AF51-3C163A91DF8B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "references", "references", "{17B63D57-9385-4790-BC48-8682125AD342}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{BD682B96-A49E-496C-B093-85904FA3474A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspectCore.Extensions.Reflection", "..\reflection\src\AspectCore.Extensions.Reflection\AspectCore.Extensions.Reflection.csproj", "{BDB5D3B0-4CC1-4BC4-951A-AACF2C5BB0E2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspectCore.Abstractions", "..\core\src\AspectCore.Abstractions\AspectCore.Abstractions.csproj", "{D2E82FEC-7753-4BC2-BF7F-777C53D009F1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspectCore.Core", "..\core\src\AspectCore.Core\AspectCore.Core.csproj", "{1E167DFD-C7D6-4EB0-9B87-F65AF97764C5}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{EE749FBD-FA9E-4391-8CCA-FA7E9DE183BD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspectCore.Extensions.Configuration.Tests", "test\AspectCore.Extensions.Configuration.Tests\AspectCore.Extensions.Configuration.Tests.csproj", "{7E643D68-6361-4611-BF65-23FF230591A5}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F031B41A-C7D1-475C-AF51-3C163A91DF8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F031B41A-C7D1-475C-AF51-3C163A91DF8B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F031B41A-C7D1-475C-AF51-3C163A91DF8B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F031B41A-C7D1-475C-AF51-3C163A91DF8B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BDB5D3B0-4CC1-4BC4-951A-AACF2C5BB0E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BDB5D3B0-4CC1-4BC4-951A-AACF2C5BB0E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BDB5D3B0-4CC1-4BC4-951A-AACF2C5BB0E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BDB5D3B0-4CC1-4BC4-951A-AACF2C5BB0E2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D2E82FEC-7753-4BC2-BF7F-777C53D009F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D2E82FEC-7753-4BC2-BF7F-777C53D009F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D2E82FEC-7753-4BC2-BF7F-777C53D009F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D2E82FEC-7753-4BC2-BF7F-777C53D009F1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1E167DFD-C7D6-4EB0-9B87-F65AF97764C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1E167DFD-C7D6-4EB0-9B87-F65AF97764C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1E167DFD-C7D6-4EB0-9B87-F65AF97764C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1E167DFD-C7D6-4EB0-9B87-F65AF97764C5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7E643D68-6361-4611-BF65-23FF230591A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7E643D68-6361-4611-BF65-23FF230591A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7E643D68-6361-4611-BF65-23FF230591A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7E643D68-6361-4611-BF65-23FF230591A5}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {F031B41A-C7D1-475C-AF51-3C163A91DF8B} = {BD682B96-A49E-496C-B093-85904FA3474A}
+ {BDB5D3B0-4CC1-4BC4-951A-AACF2C5BB0E2} = {17B63D57-9385-4790-BC48-8682125AD342}
+ {D2E82FEC-7753-4BC2-BF7F-777C53D009F1} = {17B63D57-9385-4790-BC48-8682125AD342}
+ {1E167DFD-C7D6-4EB0-9B87-F65AF97764C5} = {17B63D57-9385-4790-BC48-8682125AD342}
+ {7E643D68-6361-4611-BF65-23FF230591A5} = {EE749FBD-FA9E-4391-8CCA-FA7E9DE183BD}
+ EndGlobalSection
+EndGlobal
diff --git a/configuration/src/AspectCore.Extensions.Configuration/AspectCore.Extensions.Configuration.csproj b/configuration/src/AspectCore.Extensions.Configuration/AspectCore.Extensions.Configuration.csproj
new file mode 100644
index 00000000..43c8c25b
--- /dev/null
+++ b/configuration/src/AspectCore.Extensions.Configuration/AspectCore.Extensions.Configuration.csproj
@@ -0,0 +1,22 @@
+
+
+
+ Configuration extension system for ASP.NET Core via AspectCore-Framework.
+ AspectCore.Extensions.Configuration
+ False
+ AspectCore.Extensions.Configuration
+ AspectCore.Extensions.Configuration
+ Reflection;Aop;DynamicProxy;Configuration
+ Configuration extension system for ASP.NET Core via AspectCore-Framework.
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/configuration/src/AspectCore.Extensions.Configuration/Attributes/ConfigurationBindingAttribute.cs b/configuration/src/AspectCore.Extensions.Configuration/Attributes/ConfigurationBindingAttribute.cs
new file mode 100644
index 00000000..41fb0c4a
--- /dev/null
+++ b/configuration/src/AspectCore.Extensions.Configuration/Attributes/ConfigurationBindingAttribute.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace AspectCore.Extensions.Configuration
+{
+ public class ConfigurationBindingAttribute : ConfigurationMetadataAttribute
+ {
+ public override string[] Sections { get; }
+
+ public override string Key { get; } = null;
+
+ public override ConfigurationBindType Type { get; } = ConfigurationBindType.Class;
+
+ public ConfigurationBindingAttribute(params string[] sections)
+ {
+ Sections = sections;
+ }
+ }
+}
\ No newline at end of file
diff --git a/configuration/src/AspectCore.Extensions.Configuration/Attributes/ConfigurationMetadataAttribute.cs b/configuration/src/AspectCore.Extensions.Configuration/Attributes/ConfigurationMetadataAttribute.cs
new file mode 100644
index 00000000..be4d66bb
--- /dev/null
+++ b/configuration/src/AspectCore.Extensions.Configuration/Attributes/ConfigurationMetadataAttribute.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Linq;
+
+namespace AspectCore.Extensions.Configuration
+{
+ public abstract class ConfigurationMetadataAttribute : Attribute, IConfigurationMetadataProvider
+ {
+ public abstract string[] Sections { get; }
+ public abstract string Key { get; }
+ public abstract ConfigurationBindType Type { get; }
+
+ public string GetSection()
+ {
+ if (Sections == null || Sections.Length == 0)
+ {
+ return null;
+ }
+
+ if (Sections.Length ==1)
+ {
+ return Sections[0];
+ }
+
+ return Sections.Aggregate((x, y) => x + ":" + y);
+ }
+ }
+}
\ No newline at end of file
diff --git a/configuration/src/AspectCore.Extensions.Configuration/Attributes/ConfigurationValueAttribute.cs b/configuration/src/AspectCore.Extensions.Configuration/Attributes/ConfigurationValueAttribute.cs
new file mode 100644
index 00000000..3b76464a
--- /dev/null
+++ b/configuration/src/AspectCore.Extensions.Configuration/Attributes/ConfigurationValueAttribute.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace AspectCore.Extensions.Configuration
+{
+ public class ConfigurationValueAttribute : ConfigurationMetadataAttribute
+ {
+ public override string Key { get; }
+
+ public override ConfigurationBindType Type { get; } = ConfigurationBindType.Value;
+
+ public override string[] Sections { get; }
+
+ public ConfigurationValueAttribute(string key, params string[] sections)
+ {
+ Key = key;
+ Sections = sections;
+ }
+ }
+}
\ No newline at end of file
diff --git a/configuration/src/AspectCore.Extensions.Configuration/ConfigurationBindResolveCallback.cs b/configuration/src/AspectCore.Extensions.Configuration/ConfigurationBindResolveCallback.cs
new file mode 100644
index 00000000..ff7080f4
--- /dev/null
+++ b/configuration/src/AspectCore.Extensions.Configuration/ConfigurationBindResolveCallback.cs
@@ -0,0 +1,46 @@
+using System.Reflection;
+using AspectCore.Injector;
+using AspectCore.Extensions.Reflection;
+using Microsoft.Extensions.Configuration;
+
+namespace AspectCore.Extensions.Configuration
+{
+ public sealed class ConfigurationBindResolveCallback : IServiceResolveCallback
+ {
+ private const BindingFlags _flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
+
+ public object Invoke(IServiceResolver resolver, object instance, ServiceDefinition service)
+ {
+ if (instance == null || instance is IConfiguration)
+ {
+ return instance;
+ }
+
+ var instanceType = instance.GetType();
+ var configuration = resolver.ResolveRequired();
+ foreach (var field in instanceType.GetFields(_flags))
+ {
+ var reflector = field.GetReflector();
+ var configurationMetadata = reflector.GetCustomAttribute();
+ if (configurationMetadata == null)
+ {
+ continue;
+ }
+
+ var section = configurationMetadata.GetSection();
+ if (configurationMetadata.Type == ConfigurationBindType.Value)
+ {
+ var key = section == null ? configurationMetadata.Key : section + ":" + configurationMetadata.Key;
+ reflector.SetValue(instance, configuration.GetValue(field.FieldType, key));
+ }
+ else
+ {
+ var configurationSection = section == null ? configuration : configuration.GetSection(section);
+ reflector.SetValue(instance, configurationSection.Get(field.FieldType));
+ }
+ }
+
+ return instance;
+ }
+ }
+}
\ No newline at end of file
diff --git a/configuration/src/AspectCore.Extensions.Configuration/ConfigurationBindType.cs b/configuration/src/AspectCore.Extensions.Configuration/ConfigurationBindType.cs
new file mode 100644
index 00000000..49cd5f18
--- /dev/null
+++ b/configuration/src/AspectCore.Extensions.Configuration/ConfigurationBindType.cs
@@ -0,0 +1,8 @@
+namespace AspectCore.Extensions.Configuration
+{
+ public enum ConfigurationBindType
+ {
+ Value,
+ Class
+ }
+}
\ No newline at end of file
diff --git a/configuration/src/AspectCore.Extensions.Configuration/IConfigurationMetadataProvider.cs b/configuration/src/AspectCore.Extensions.Configuration/IConfigurationMetadataProvider.cs
new file mode 100644
index 00000000..d82fd669
--- /dev/null
+++ b/configuration/src/AspectCore.Extensions.Configuration/IConfigurationMetadataProvider.cs
@@ -0,0 +1,11 @@
+namespace AspectCore.Extensions.Configuration
+{
+ public interface IConfigurationMetadataProvider
+ {
+ string[] Sections { get; }
+
+ string Key { get; }
+
+ ConfigurationBindType Type { get; }
+ }
+}
\ No newline at end of file
diff --git a/configuration/src/AspectCore.Extensions.Configuration/ServiceContainerExtensions.cs b/configuration/src/AspectCore.Extensions.Configuration/ServiceContainerExtensions.cs
new file mode 100644
index 00000000..c68f00a3
--- /dev/null
+++ b/configuration/src/AspectCore.Extensions.Configuration/ServiceContainerExtensions.cs
@@ -0,0 +1,19 @@
+using System;
+using AspectCore.Injector;
+
+namespace AspectCore.Extensions.Configuration
+{
+ public static class ServiceContainerExtensions
+ {
+ public static IServiceContainer AddConfigurationInject(this IServiceContainer container)
+ {
+ if (container == null)
+ {
+ throw new ArgumentNullException(nameof(container));
+ }
+
+ container.AddType(Lifetime.Singleton);
+ return container;
+ }
+ }
+}
\ No newline at end of file
diff --git a/configuration/test/AspectCore.Extensions.Configuration.Tests/AspectCore.Extensions.Configuration.Tests.csproj b/configuration/test/AspectCore.Extensions.Configuration.Tests/AspectCore.Extensions.Configuration.Tests.csproj
new file mode 100644
index 00000000..3d3fbe01
--- /dev/null
+++ b/configuration/test/AspectCore.Extensions.Configuration.Tests/AspectCore.Extensions.Configuration.Tests.csproj
@@ -0,0 +1,22 @@
+
+
+
+ netcoreapp2.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/configuration/test/AspectCore.Extensions.Configuration.Tests/ConfigurationBindingTest.cs b/configuration/test/AspectCore.Extensions.Configuration.Tests/ConfigurationBindingTest.cs
new file mode 100644
index 00000000..cd566aba
--- /dev/null
+++ b/configuration/test/AspectCore.Extensions.Configuration.Tests/ConfigurationBindingTest.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using AspectCore.Injector;
+using Microsoft.Extensions.Configuration;
+using Xunit;
+
+namespace AspectCore.Extensions.Configuration.Tests
+{
+ public class ConfigurationBindingTest
+ {
+ [Fact]
+ public void LoadBinding()
+ {
+ var dict = new Dictionary
+ {
+ {"creator:age", "24"},
+ {"creator:name", "lemon"}
+ };
+ var builder = new ConfigurationBuilder().AddEnvironmentVariables();
+ builder.AddInMemoryCollection(dict);
+ var configuration = builder.Build();
+ var container = new ServiceContainer();
+ container.AddInstance(configuration);
+ container.AddConfigurationInject();
+ container.AddType();
+ var service = container.Build().Resolve();
+ Assert.Equal(service.ToString(), "lemon-24");
+ }
+ }
+
+ public class Config
+ {
+ public string Name { get; set; }
+
+ public int Age { get; set; }
+ }
+
+ public class BindConfigService
+ {
+ [ConfigurationBinding("creator")]
+ private Config _config;
+
+ public override string ToString()
+ {
+ return $"{_config.Name}-{_config.Age}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/configuration/test/AspectCore.Extensions.Configuration.Tests/ConfigurationValueTest.cs b/configuration/test/AspectCore.Extensions.Configuration.Tests/ConfigurationValueTest.cs
new file mode 100644
index 00000000..e5bb3e4b
--- /dev/null
+++ b/configuration/test/AspectCore.Extensions.Configuration.Tests/ConfigurationValueTest.cs
@@ -0,0 +1,43 @@
+using System.Collections.Generic;
+using Microsoft.Extensions.Configuration;
+using Xunit;
+using AspectCore.Injector;
+
+namespace AspectCore.Extensions.Configuration.Tests
+{
+ public class ConfigurationValueTest
+ {
+ [Fact]
+ public void LoadValue()
+ {
+ var dict = new Dictionary
+ {
+ {"creator:age", "24"},
+ {"creator:name", "lemon"}
+ };
+ var builder = new ConfigurationBuilder().AddEnvironmentVariables();
+ builder.AddInMemoryCollection(dict);
+ var configuration = builder.Build();
+ var container = new ServiceContainer();
+ container.AddInstance(configuration);
+ container.AddConfigurationInject();
+ container.AddType();
+ var service = container.Build().Resolve();
+ Assert.Equal(service.ToString(), "lemon-24");
+ }
+ }
+
+ public class ValueConfigService
+ {
+ [ConfigurationValue("age", "creator")]
+ private int age;
+
+ [ConfigurationValue("name", "creator")]
+ private string name;
+
+ public override string ToString()
+ {
+ return $"{name}-{age}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/performance/AspectCore.IoC.Benchmarks/SimpleObjectBenchmarks.cs b/core/performance/AspectCore.IoC.Benchmarks/SimpleObjectBenchmarks.cs
index 0f00dc16..cdafd951 100644
--- a/core/performance/AspectCore.IoC.Benchmarks/SimpleObjectBenchmarks.cs
+++ b/core/performance/AspectCore.IoC.Benchmarks/SimpleObjectBenchmarks.cs
@@ -60,32 +60,32 @@ public SimpleObjectBenchmarks()
dryIocContainer.Register(typeof(IRepository<>), typeof(Repository<>));
}
- //[Benchmark]
+ [Benchmark]
public IUserService AspectCoreIoC()
{
return serviceResolver.Resolve();
}
- //[Benchmark]
+ [Benchmark]
public IUserService MicrosoftDependencyInjection()
{
return serviceProvider.GetService();
}
- //[Benchmark]
+ [Benchmark]
public IUserService Autofac()
{
return autofacContainer.Resolve();
}
- //[Benchmark]
+ [Benchmark]
public IUserService ZkWebIoC()
{
return zkWebContainer.Resolve(ZKWebStandard.Ioc.IfUnresolved.Throw, null);
}
- //[Benchmark]
+ [Benchmark]
public IUserService DryIoC()
{
return dryIocContainer.Resolve();
diff --git a/core/src/AspectCore.Abstractions/AspectCore.Abstractions.csproj b/core/src/AspectCore.Abstractions/AspectCore.Abstractions.csproj
index 5205be4a..6acf2524 100644
--- a/core/src/AspectCore.Abstractions/AspectCore.Abstractions.csproj
+++ b/core/src/AspectCore.Abstractions/AspectCore.Abstractions.csproj
@@ -7,18 +7,17 @@
AspectCore.Abstractions
AspectCore.Abstractions
AspectCore.Abstractions
- DynamicProxy;Aop;Aspect;AspectCore;Intercepter
+ DynamicProxy;Aop;Aspect;AspectCore;Interceptor
The abstract design of the AspectCore framework.
netstandard2.0;net45
-
+
-
-
+
-
+
-
+
diff --git a/core/src/AspectCore.Abstractions/Injector/IManyEnumerable.cs b/core/src/AspectCore.Abstractions/Injector/IManyEnumerable.cs
index 4ede5aab..f9c64b64 100644
--- a/core/src/AspectCore.Abstractions/Injector/IManyEnumerable.cs
+++ b/core/src/AspectCore.Abstractions/Injector/IManyEnumerable.cs
@@ -4,7 +4,7 @@
namespace AspectCore.Injector
{
- [NonAspect]
+ [NonAspect, NonCallback]
public interface IManyEnumerable : IEnumerable, IEnumerable
{
}
diff --git a/core/src/AspectCore.Abstractions/Injector/IServiceResolveCallback.cs b/core/src/AspectCore.Abstractions/Injector/IServiceResolveCallback.cs
new file mode 100644
index 00000000..7dfd8994
--- /dev/null
+++ b/core/src/AspectCore.Abstractions/Injector/IServiceResolveCallback.cs
@@ -0,0 +1,15 @@
+using System;
+using AspectCore.DynamicProxy;
+
+namespace AspectCore.Injector
+{
+ [NonAspect, NonCallback]
+ public interface IServiceResolveCallback
+ {
+ object Invoke(IServiceResolver resolver, object instance, ServiceDefinition service);
+ }
+
+ public sealed class NonCallback : Attribute
+ {
+ }
+}
\ No newline at end of file
diff --git a/core/src/AspectCore.Core/AspectCore.Core.csproj b/core/src/AspectCore.Core/AspectCore.Core.csproj
index 85aa5ea0..644e5f3e 100644
--- a/core/src/AspectCore.Core/AspectCore.Core.csproj
+++ b/core/src/AspectCore.Core/AspectCore.Core.csproj
@@ -6,17 +6,17 @@
true
AspectCore.Core
AspectCore.Core
- DynamicProxy;Aop;Aspect;AspectCore;Intercepter
+ DynamicProxy;Aop;Aspect;AspectCore;Interceptor
The implementation of the AspectCore framework.
- netstandard2.0;net45
+ net45;netstandard2.0
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/core/src/AspectCore.Core/Injector/Extensions/ServiceDefinitionExtensions.cs b/core/src/AspectCore.Core/Injector/Extensions/ServiceDefinitionExtensions.cs
index e0bc02f6..1a011591 100644
--- a/core/src/AspectCore.Core/Injector/Extensions/ServiceDefinitionExtensions.cs
+++ b/core/src/AspectCore.Core/Injector/Extensions/ServiceDefinitionExtensions.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Concurrent;
using System.Diagnostics;
using System.Reflection;
using System.Linq;
@@ -9,6 +10,8 @@ namespace AspectCore.Injector
{
internal static class ServiceDefinitionExtensions
{
+ private static readonly ConcurrentDictionary _callbackMap = new ConcurrentDictionary();
+
internal static Type GetImplementationType(this ServiceDefinition serviceDefinition)
{
if (serviceDefinition is TypeServiceDefinition typeServiceDefinition)
@@ -60,5 +63,10 @@ internal static bool IsManyEnumerable(this ServiceDefinition serviceDefinition)
var serviceTypeInfo = serviceDefinition.ServiceType.GetTypeInfo();
return serviceTypeInfo.IsGenericType && serviceTypeInfo.GetGenericTypeDefinition() == typeof(IManyEnumerable<>);
}
+
+ internal static bool RequiredResolveCallback(this ServiceDefinition serviceDefinition)
+ {
+ return _callbackMap.GetOrAdd(serviceDefinition, service => !service.ServiceType.GetReflector().IsDefined());
+ }
}
}
\ No newline at end of file
diff --git a/core/src/AspectCore.Core/Injector/IServiceResolveCallbackProvider.cs b/core/src/AspectCore.Core/Injector/IServiceResolveCallbackProvider.cs
new file mode 100644
index 00000000..725f5a19
--- /dev/null
+++ b/core/src/AspectCore.Core/Injector/IServiceResolveCallbackProvider.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace AspectCore.Injector
+{
+ internal interface IServiceResolveCallbackProvider
+ {
+ IServiceResolveCallback[] ServiceResolveCallbacks { get; }
+ }
+}
\ No newline at end of file
diff --git a/core/src/AspectCore.Core/Injector/PropertyInjectorCallback.cs b/core/src/AspectCore.Core/Injector/PropertyInjectorCallback.cs
new file mode 100644
index 00000000..4d4be565
--- /dev/null
+++ b/core/src/AspectCore.Core/Injector/PropertyInjectorCallback.cs
@@ -0,0 +1,17 @@
+namespace AspectCore.Injector
+{
+ public class PropertyInjectorCallback : IServiceResolveCallback
+ {
+ public object Invoke(IServiceResolver resolver, object instance, ServiceDefinition service)
+ {
+ if (instance == null || !service.RequiredPropertyInjection())
+ {
+ return instance;
+ }
+ var injectorFactory = resolver.Resolve();
+ var injector = injectorFactory.Create(instance.GetType());
+ injector.Invoke(instance);
+ return instance;
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/src/AspectCore.Core/Injector/ServiceCallSiteResolver.cs b/core/src/AspectCore.Core/Injector/ServiceCallSiteResolver.cs
index 8f44a8ae..38ca2750 100644
--- a/core/src/AspectCore.Core/Injector/ServiceCallSiteResolver.cs
+++ b/core/src/AspectCore.Core/Injector/ServiceCallSiteResolver.cs
@@ -12,6 +12,7 @@ internal class ServiceCallSiteResolver
{
private readonly ConstructorCallSiteResolver _constructorCallSiteResolver;
private readonly ConcurrentDictionary> _resolvedCallSites;
+
public ServiceCallSiteResolver(ServiceTable serviceTable)
{
_constructorCallSiteResolver = new ConstructorCallSiteResolver(serviceTable);
@@ -20,31 +21,30 @@ public ServiceCallSiteResolver(ServiceTable serviceTable)
internal Func Resolve(ServiceDefinition service)
{
- return _resolvedCallSites.GetOrAdd(service, ResolvePropertyInject);
+ return _resolvedCallSites.GetOrAdd(service, ResolveCallback);
}
- internal Func ResolvePropertyInject(ServiceDefinition service)
+ private Func ResolveCallback(ServiceDefinition service)
{
var callSite = ResolveInternal(service);
- if (!service.RequiredPropertyInjection())
+ if (!service.RequiredResolveCallback())
{
return callSite;
}
+
return resolver =>
{
var instance = callSite(resolver);
- if (instance == null)
+ var callbacks = resolver.ServiceResolveCallbacks;
+ for (var i = 0; i < callbacks.Length; i++)
{
- return null;
+ instance = callbacks[i].Invoke(resolver, instance, service);
}
- var injectorFactory = resolver.Resolve();
- var injector = injectorFactory.Create(instance.GetType());
- injector.Invoke(instance);
return instance;
};
}
- internal Func ResolveInternal(ServiceDefinition service)
+ private Func ResolveInternal(ServiceDefinition service)
{
switch (service)
{
@@ -56,13 +56,15 @@ internal Func ResolveInternal(ServiceDefinition service
return delegateServiceDefinition.ImplementationDelegate;
case TypeServiceDefinition typeServiceDefinition:
return ResolveTypeService(typeServiceDefinition);
- case ManyEnumerableServiceDefintion manyEnumerableServiceDefintion:
- return ResolveManyEnumerableService(manyEnumerableServiceDefintion);
- case EnumerableServiceDefintion enumerableServiceDefintion:
- return ResolveEnumerableService(enumerableServiceDefintion);
+ case ManyEnumerableServiceDefintion manyEnumerableServiceDefinition:
+ return ResolveManyEnumerableService(manyEnumerableServiceDefinition);
+ case EnumerableServiceDefintion enumerableServiceDefinition:
+ return ResolveEnumerableService(enumerableServiceDefinition);
default:
return resolver => null;
- };
+ }
+
+ ;
}
private Func ResolveManyEnumerableService(ManyEnumerableServiceDefintion manyEnumerableServiceDefintion)
@@ -77,6 +79,7 @@ private Func ResolveManyEnumerableService(ManyEnumerabl
{
instance.SetValue(resolver.ResolveDefinition(elementDefinitions[i]), i);
}
+
return ActivatorUtils.CreateManyEnumerable(elementType, instance);
};
}
@@ -94,6 +97,7 @@ private Func ResolveEnumerableService(EnumerableService
var element = resolver.ResolveDefinition(elementDefinitions[i]);
instance.SetValue(element, i);
}
+
return instance;
};
}
@@ -104,7 +108,8 @@ private Func ResolveProxyService(ProxyServiceDefinition
{
return ResolveTypeService(proxyServiceDefinition.ClassProxyServiceDefinition);
}
- var proxyConstructor = proxyServiceDefinition.ProxyType.GetTypeInfo().GetConstructor(new Type[] { typeof(IAspectActivatorFactory), proxyServiceDefinition.ServiceType });
+
+ var proxyConstructor = proxyServiceDefinition.ProxyType.GetTypeInfo().GetConstructor(new Type[] {typeof(IAspectActivatorFactory), proxyServiceDefinition.ServiceType});
var reflector = proxyConstructor.GetReflector();
var serviceResolver = Resolve(proxyServiceDefinition.ServiceDefinition);
return resolver => reflector.Invoke(resolver.ResolveRequired(), serviceResolver(resolver));
@@ -115,8 +120,10 @@ private Func ResolveTypeService(TypeServiceDefinition t
var callSite = _constructorCallSiteResolver.Resolve(typeServiceDefinition.ImplementationType);
if (callSite == null)
{
- throw new InvalidOperationException($"Failed to create instance of type '{typeServiceDefinition.ServiceType}'. Possible reason is cannot match the best constructor of type '{typeServiceDefinition.ImplementationType}'.");
+ throw new InvalidOperationException(
+ $"Failed to create instance of type '{typeServiceDefinition.ServiceType}'. Possible reason is cannot match the best constructor of type '{typeServiceDefinition.ImplementationType}'.");
}
+
return callSite;
}
}
diff --git a/core/src/AspectCore.Core/Injector/ServiceContainer.cs b/core/src/AspectCore.Core/Injector/ServiceContainer.cs
index 9b1e8b98..2f9d68e6 100644
--- a/core/src/AspectCore.Core/Injector/ServiceContainer.cs
+++ b/core/src/AspectCore.Core/Injector/ServiceContainer.cs
@@ -73,6 +73,9 @@ private void AddInternalServices()
Singletons.AddInstance(_configuration);
if (!Contains(typeof(ITransientServiceAccessor<>)))
Singletons.AddType(typeof(ITransientServiceAccessor<>), typeof(TransientServiceAccessor<>));
+
+ //add service resolve callbacks
+ Scopeds.AddType();
//add DynamicProxy services
Singletons.AddType();
diff --git a/core/src/AspectCore.Core/Injector/ServiceResolver.cs b/core/src/AspectCore.Core/Injector/ServiceResolver.cs
index 7d6b5a44..485ec98e 100644
--- a/core/src/AspectCore.Core/Injector/ServiceResolver.cs
+++ b/core/src/AspectCore.Core/Injector/ServiceResolver.cs
@@ -1,15 +1,16 @@
using System;
using System.Collections.Concurrent;
+using System.Collections.Generic;
using System.Linq;
using AspectCore.DynamicProxy;
namespace AspectCore.Injector
{
[NonAspect]
- internal class ServiceResolver : IServiceResolver
+ internal sealed class ServiceResolver : IServiceResolver,IServiceResolveCallbackProvider
{
- private readonly ConcurrentDictionary _resolvedScopedServcies;
- private readonly ConcurrentDictionary _resolvedSingletonServcies;
+ private readonly ConcurrentDictionary _resolvedScopedServices;
+ private readonly ConcurrentDictionary _resolvedSingletonServices;
private readonly ServiceTable _serviceTable;
private readonly ServiceCallSiteResolver _serviceCallSiteResolver;
internal readonly ServiceResolver _root;
@@ -18,18 +19,22 @@ public ServiceResolver(IServiceContainer serviceContainer)
{
_serviceTable = new ServiceTable(serviceContainer.Configuration);
_serviceTable.Populate(serviceContainer);
- _resolvedScopedServcies = new ConcurrentDictionary();
- _resolvedSingletonServcies = new ConcurrentDictionary();
+ _resolvedScopedServices = new ConcurrentDictionary();
+ _resolvedSingletonServices = new ConcurrentDictionary();
_serviceCallSiteResolver = new ServiceCallSiteResolver(_serviceTable);
+ ServiceResolveCallbacks = this.ResolveMany().ToArray();
}
+ public IServiceResolveCallback[] ServiceResolveCallbacks { get; }
+
public ServiceResolver(ServiceResolver root)
{
_root = root;
_serviceTable = root._serviceTable;
- _resolvedSingletonServcies = root._resolvedSingletonServcies;
+ _resolvedSingletonServices = root._resolvedSingletonServices;
_serviceCallSiteResolver = root._serviceCallSiteResolver;
- _resolvedScopedServcies = new ConcurrentDictionary();
+ _resolvedScopedServices = new ConcurrentDictionary();
+ ServiceResolveCallbacks = this.ResolveMany().ToArray();
}
public object GetService(Type serviceType)
@@ -59,9 +64,9 @@ internal object ResolveDefinition(ServiceDefinition definition)
switch (definition.Lifetime)
{
case Lifetime.Singleton:
- return _resolvedSingletonServcies.GetOrAdd(definition, d => _serviceCallSiteResolver.Resolve(d)(_root ?? this));
+ return _resolvedSingletonServices.GetOrAdd(definition, d => _serviceCallSiteResolver.Resolve(d)(_root ?? this));
case Lifetime.Scoped:
- return _resolvedScopedServcies.GetOrAdd(definition, d => _serviceCallSiteResolver.Resolve(d)(this));
+ return _resolvedScopedServices.GetOrAdd(definition, d => _serviceCallSiteResolver.Resolve(d)(this));
default:
return _serviceCallSiteResolver.Resolve(definition)(this);
}
@@ -70,7 +75,7 @@ internal object ResolveDefinition(ServiceDefinition definition)
#region IDisposable Support
private bool disposedValue = false;
- protected virtual void Dispose(bool disposing)
+ private void Dispose(bool disposing)
{
if (!disposedValue)
{
@@ -78,13 +83,13 @@ protected virtual void Dispose(bool disposing)
{
if (_root == null || _root == this)
{
- foreach (var singleton in _resolvedSingletonServcies.Where(x => x.Value != this))
+ foreach (var singleton in _resolvedSingletonServices.Where(x => x.Value != this))
{
var disposable = singleton.Value as IDisposable;
disposable?.Dispose();
}
}
- foreach (var scoped in _resolvedScopedServcies.Where(x => x.Value != this))
+ foreach (var scoped in _resolvedScopedServices.Where(x => x.Value != this))
{
var disposable = scoped.Value as IDisposable;
disposable?.Dispose();
diff --git a/extras/sample/AspectCore.Extensions.DependencyInjection.Sample/Startup.cs b/extras/sample/AspectCore.Extensions.DependencyInjection.Sample/Startup.cs
index ff02fd08..344c3e2b 100644
--- a/extras/sample/AspectCore.Extensions.DependencyInjection.Sample/Startup.cs
+++ b/extras/sample/AspectCore.Extensions.DependencyInjection.Sample/Startup.cs
@@ -34,7 +34,7 @@ public IServiceProvider ConfigureServices(IServiceCollection services)
config.Interceptors.AddTyped();
});
//方式二步骤2.调用services.BuildAspectCoreServiceProvider构建动态代理服务解析器
- return services.BuildAspectCoreServiceProvider();
+ return services.BuildAspectInjectorProvider();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
diff --git a/extras/src/AspectCore.Extensions.DependencyInjection/DynamicProxyServiceProviderFactory.cs b/extras/src/AspectCore.Extensions.DependencyInjection/DynamicProxyServiceProviderFactory.cs
index 83bd79aa..34463d5e 100644
--- a/extras/src/AspectCore.Extensions.DependencyInjection/DynamicProxyServiceProviderFactory.cs
+++ b/extras/src/AspectCore.Extensions.DependencyInjection/DynamicProxyServiceProviderFactory.cs
@@ -12,7 +12,7 @@ public IServiceCollection CreateBuilder(IServiceCollection services)
public IServiceProvider CreateServiceProvider(IServiceCollection containerBuilder)
{
- return containerBuilder.BuildAspectCoreServiceProvider();
+ return containerBuilder.BuildDynamicProxyServiceProvider();
}
}
}
diff --git a/extras/src/AspectCore.Extensions.DependencyInjection/ServiceCollectionBuildExtensions.cs b/extras/src/AspectCore.Extensions.DependencyInjection/ServiceCollectionBuildExtensions.cs
index 68015018..1887d998 100644
--- a/extras/src/AspectCore.Extensions.DependencyInjection/ServiceCollectionBuildExtensions.cs
+++ b/extras/src/AspectCore.Extensions.DependencyInjection/ServiceCollectionBuildExtensions.cs
@@ -14,11 +14,28 @@ namespace AspectCore.Extensions.DependencyInjection
{
public static class ServiceCollectionBuildExtensions
{
+ [Obsolete("Use BuildAspectInjectorProvider to return AspectCore Injector, or Use BuildDynamicProxyServiceProvider to return MSDI ServiceProvider.", true)]
public static IServiceProvider BuildAspectCoreServiceProvider(this IServiceCollection services)
{
- return services.AddDynamicProxyCore().BuildServiceProvider(false);
+ return services.BuildDynamicProxyServiceProvider();
}
- public static IServiceCollection AddDynamicProxyCore(this IServiceCollection services)
+
+ public static ServiceProvider BuildDynamicProxyServiceProvider(this IServiceCollection services)
+ {
+ return services.WeaveDynamicProxyService().BuildServiceProvider();
+ }
+
+ public static ServiceProvider BuildDynamicProxyServiceProvider(this IServiceCollection services, bool validateScopes)
+ {
+ return services.WeaveDynamicProxyService().BuildServiceProvider(validateScopes);
+ }
+
+ public static ServiceProvider BuildDynamicProxyServiceProvider(this IServiceCollection services, ServiceProviderOptions options)
+ {
+ return services.WeaveDynamicProxyService().BuildServiceProvider(options);
+ }
+
+ public static IServiceCollection WeaveDynamicProxyService(this IServiceCollection services)
{
if (services == null)
{
@@ -33,7 +50,7 @@ public static IServiceCollection AddDynamicProxyCore(this IServiceCollection ser
IServiceCollection dynamicProxyServices = new ServiceCollection();
foreach (var service in services)
{
- if (serviceValidator.TryValidate(service, out Type implementationType))
+ if (serviceValidator.TryValidate(service, out var implementationType))
dynamicProxyServices.Add(MakeProxyService(service, implementationType, proxyTypeGenerator));
else
dynamicProxyServices.Add(service);
@@ -44,37 +61,36 @@ public static IServiceCollection AddDynamicProxyCore(this IServiceCollection ser
return dynamicProxyServices;
}
-
private static ServiceDescriptor MakeProxyService(ServiceDescriptor descriptor, Type implementationType, IProxyTypeGenerator proxyTypeGenerator)
{
var serviceTypeInfo = descriptor.ServiceType.GetTypeInfo();
if (serviceTypeInfo.IsClass)
{
return ServiceDescriptor.Describe(
- descriptor.ServiceType,
- proxyTypeGenerator.CreateClassProxyType(descriptor.ServiceType, implementationType),
- descriptor.Lifetime);
+ descriptor.ServiceType,
+ proxyTypeGenerator.CreateClassProxyType(descriptor.ServiceType, implementationType),
+ descriptor.Lifetime);
}
else if (serviceTypeInfo.IsGenericTypeDefinition)
{
return ServiceDescriptor.Describe(
- descriptor.ServiceType,
- proxyTypeGenerator.CreateClassProxyType(implementationType, implementationType),
- descriptor.Lifetime);
+ descriptor.ServiceType,
+ proxyTypeGenerator.CreateClassProxyType(implementationType, implementationType),
+ descriptor.Lifetime);
}
else
{
var proxyType = proxyTypeGenerator.CreateInterfaceProxyType(descriptor.ServiceType, implementationType);
return ServiceDescriptor.Describe(
- descriptor.ServiceType,
- CreateFactory(descriptor, proxyType),
- descriptor.Lifetime);
+ descriptor.ServiceType,
+ CreateFactory(descriptor, proxyType),
+ descriptor.Lifetime);
}
}
private static Func CreateFactory(ServiceDescriptor descriptor, Type proxyType)
{
- var proxyConstructor = proxyType.GetTypeInfo().GetConstructor(new Type[] { typeof(IAspectActivatorFactory), descriptor.ServiceType });
+ var proxyConstructor = proxyType.GetTypeInfo().GetConstructor(new Type[] {typeof(IAspectActivatorFactory), descriptor.ServiceType});
var reflector = proxyConstructor.GetReflector();
if (descriptor.ImplementationInstance != null)
{
diff --git a/extras/src/AspectCore.Extensions.DependencyInjection/ServiceCollectionExtensions.cs b/extras/src/AspectCore.Extensions.DependencyInjection/ServiceCollectionExtensions.cs
index dfe3e054..77628660 100644
--- a/extras/src/AspectCore.Extensions.DependencyInjection/ServiceCollectionExtensions.cs
+++ b/extras/src/AspectCore.Extensions.DependencyInjection/ServiceCollectionExtensions.cs
@@ -11,7 +11,13 @@ namespace AspectCore.Extensions.DependencyInjection
{
public static class ServiceCollectionExtensions
{
+ [Obsolete("Use ConfigureDynamicProxy")]
public static IServiceCollection AddDynamicProxy(this IServiceCollection services, Action configure = null)
+ {
+ return ConfigureDynamicProxy(services, configure);
+ }
+
+ public static IServiceCollection ConfigureDynamicProxy(this IServiceCollection services, Action configure = null)
{
if (services == null)
{
@@ -24,7 +30,7 @@ public static IServiceCollection AddDynamicProxy(this IServiceCollection service
if (configurationService == null)
{
- services.AddSingleton(configuration);
+ services.AddSingleton(configuration);
}
return services;
@@ -37,13 +43,7 @@ internal static IServiceCollection TryAddDynamicProxyServices(this IServiceColle
throw new ArgumentNullException(nameof(services));
}
- var configurationService = services.LastOrDefault(x => x.ServiceType == typeof(IAspectConfiguration) && x.ImplementationInstance != null);
- var configuration = (IAspectConfiguration)configurationService?.ImplementationInstance ?? new AspectConfiguration();
-
- if (configurationService == null)
- {
- services.AddSingleton(configuration);
- }
+ //services.ConfigureDynamicProxy();
services.TryAddTransient(typeof(IManyEnumerable<>), typeof(ManyEnumerable<>));
services.TryAddScoped();
diff --git a/extras/src/AspectCore.Extensions.DependencyInjection/ServiceCollectionToContainerExtensions.cs b/extras/src/AspectCore.Extensions.DependencyInjection/ServiceCollectionToContainerExtensions.cs
index 08766cdf..347a03de 100644
--- a/extras/src/AspectCore.Extensions.DependencyInjection/ServiceCollectionToContainerExtensions.cs
+++ b/extras/src/AspectCore.Extensions.DependencyInjection/ServiceCollectionToContainerExtensions.cs
@@ -8,12 +8,25 @@ namespace AspectCore.Extensions.DependencyInjection
{
public static class ServiceCollectionToContainerExtensions
{
+ public static IServiceProvider BuildAspectInjectorProvider(this IServiceCollection services)
+ {
+ return BuildAspectInjectorProvider(services, null);
+ }
+
+ public static IServiceProvider BuildAspectInjectorProvider(this IServiceCollection services, Action additional)
+ {
+ var container = services.ToServiceContainer();
+ additional?.Invoke(container);
+ return container.Build();
+ }
+
public static IServiceContainer ToServiceContainer(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
+
services.AddScoped();
services.AddScoped();
return new ServiceContainer(services.AddAspectCoreContainer().Select(Replace));
@@ -24,7 +37,8 @@ public static IServiceCollection AddAspectCoreContainer(this IServiceCollection
if (services == null)
{
throw new ArgumentNullException(nameof(services));
- }
+ }
+
services.TryAddSingleton, AspectCoreServiceProviderFactory>();
return services;
}
diff --git a/extras/src/AspectCore.Extensions.Hosting/AspectCore.Extensions.Hosting.csproj b/extras/src/AspectCore.Extensions.Hosting/AspectCore.Extensions.Hosting.csproj
index f15659cf..e305a3ec 100644
--- a/extras/src/AspectCore.Extensions.Hosting/AspectCore.Extensions.Hosting.csproj
+++ b/extras/src/AspectCore.Extensions.Hosting/AspectCore.Extensions.Hosting.csproj
@@ -4,7 +4,7 @@
netstandard2.0
-
+
diff --git a/extras/test/AspectCore.Extensions.DependencyInjection.Test/AdditionalInterceptorSelectorTests.cs b/extras/test/AspectCore.Extensions.DependencyInjection.Test/AdditionalInterceptorSelectorTests.cs
index 596d24cb..c4a5f390 100644
--- a/extras/test/AspectCore.Extensions.DependencyInjection.Test/AdditionalInterceptorSelectorTests.cs
+++ b/extras/test/AspectCore.Extensions.DependencyInjection.Test/AdditionalInterceptorSelectorTests.cs
@@ -16,7 +16,7 @@ public void ImplementationMethod_Test()
{
var services = new ServiceCollection();
services.AddTransient();
- var provider = services.BuildAspectCoreServiceProvider();
+ var provider = services.BuildAspectInjectorProvider();
var service = provider.GetService();
var val = service.GetValue("le");
Assert.Equal("lemon", val);
diff --git a/extras/test/AspectCore.Extensions.DependencyInjection.Test/UseMicrosoftDISpecificationTests.cs b/extras/test/AspectCore.Extensions.DependencyInjection.Test/UseMicrosoftDISpecificationTests.cs
index 4d2fa6f1..0ff9d51e 100644
--- a/extras/test/AspectCore.Extensions.DependencyInjection.Test/UseMicrosoftDISpecificationTests.cs
+++ b/extras/test/AspectCore.Extensions.DependencyInjection.Test/UseMicrosoftDISpecificationTests.cs
@@ -14,7 +14,7 @@ protected override IServiceProvider CreateServiceProvider(IServiceCollection ser
config.Interceptors.AddDelegate((ctx, next) => next(ctx));
});
- return serviceCollection.BuildAspectCoreServiceProvider();
+ return serviceCollection.BuildDynamicProxyServiceProvider();
}
}
}
\ No newline at end of file