Skip to content

Commit

Permalink
Feature/auto configuration (#134)
Browse files Browse the repository at this point in the history
* Add IServiceResolveCallback Api

* Update version of Microsoft.Extensions.Hosting

* Refactor services.BuildxxxProvider

* Fix csproj

* performance optimization

* Add AspectCore.Extensions.Configuration project

* Refactor

* Provider configuration bind

* Fix scope resolve
  • Loading branch information
liuhaoyang authored Sep 10, 2018
1 parent 76e0ec8 commit 178eb27
Show file tree
Hide file tree
Showing 32 changed files with 505 additions and 77 deletions.
4 changes: 2 additions & 2 deletions build/version.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<VersionMajor>0</VersionMajor>
<VersionMinor>7</VersionMinor>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<VersionPatch>0</VersionPatch>
<VersionQuality></VersionQuality>
<VersionPrefix>$(VersionMajor).$(VersionMinor).$(VersionPatch)</VersionPrefix>
Expand Down
53 changes: 53 additions & 0 deletions configuration/AspectCore.Extensions.Configuration.sln
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\build\common.props" />
<PropertyGroup>
<Description>Configuration extension system for ASP.NET Core via AspectCore-Framework.</Description>
<AssemblyTitle>AspectCore.Extensions.Configuration</AssemblyTitle>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<AssemblyName>AspectCore.Extensions.Configuration</AssemblyName>
<PackageId>AspectCore.Extensions.Configuration</PackageId>
<PackageTags>Reflection;Aop;DynamicProxy;Configuration</PackageTags>
<PackageReleaseNotes>Configuration extension system for ASP.NET Core via AspectCore-Framework.</PackageReleaseNotes>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\core\src\AspectCore.Abstractions\AspectCore.Abstractions.csproj" />
<ProjectReference Include="..\..\..\reflection\src\AspectCore.Extensions.Reflection\AspectCore.Extensions.Reflection.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.1.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
Original file line number Diff line number Diff line change
@@ -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<IConfiguration>();
foreach (var field in instanceType.GetFields(_flags))
{
var reflector = field.GetReflector();
var configurationMetadata = reflector.GetCustomAttribute<ConfigurationMetadataAttribute>();
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;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace AspectCore.Extensions.Configuration
{
public enum ConfigurationBindType
{
Value,
Class
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace AspectCore.Extensions.Configuration
{
public interface IConfigurationMetadataProvider
{
string[] Sections { get; }

string Key { get; }

ConfigurationBindType Type { get; }
}
}
Original file line number Diff line number Diff line change
@@ -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<IServiceResolveCallback, ConfigurationBindResolveCallback>(Lifetime.Singleton);
return container;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\core\src\AspectCore.Core\AspectCore.Core.csproj" />
<ProjectReference Include="..\..\src\AspectCore.Extensions.Configuration\AspectCore.Extensions.Configuration.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -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<string, string>
{
{"creator:age", "24"},
{"creator:name", "lemon"}
};
var builder = new ConfigurationBuilder().AddEnvironmentVariables();
builder.AddInMemoryCollection(dict);
var configuration = builder.Build();
var container = new ServiceContainer();
container.AddInstance<IConfiguration>(configuration);
container.AddConfigurationInject();
container.AddType<BindConfigService>();
var service = container.Build().Resolve<BindConfigService>();
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}";
}
}
}
Original file line number Diff line number Diff line change
@@ -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<string, string>
{
{"creator:age", "24"},
{"creator:name", "lemon"}
};
var builder = new ConfigurationBuilder().AddEnvironmentVariables();
builder.AddInMemoryCollection(dict);
var configuration = builder.Build();
var container = new ServiceContainer();
container.AddInstance<IConfiguration>(configuration);
container.AddConfigurationInject();
container.AddType<ValueConfigService>();
var service = container.Build().Resolve<ValueConfigService>();
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}";
}
}
}
Loading

0 comments on commit 178eb27

Please sign in to comment.