Skip to content

Commit c239b88

Browse files
committed
Add support for Autofac
1 parent 79c82cf commit c239b88

22 files changed

+314
-54
lines changed

.github/workflows/reflection-events-cd-nuget.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,11 @@ jobs:
2828
- name: Build
2929
run: dotnet build src\ReflectionEventing\ReflectionEventing.csproj --configuration Release --no-restore -p:SourceLinkEnabled=true
3030

31+
- name: Build
32+
run: dotnet build src\ReflectionEventing.Autofac\ReflectionEventing.Autofac.csproj --configuration Release --no-restore -p:SourceLinkEnabled=true
33+
34+
- name: Build
35+
run: dotnet build src\ReflectionEventing.DependencyInjection\ReflectionEventing.DependencyInjection.csproj --configuration Release --no-restore -p:SourceLinkEnabled=true
36+
3137
- name: Publish the package to NuGet.org
3238
run: nuget push **\*.nupkg -NonInteractive -SkipDuplicate -Source 'https://api.nuget.org/v3/index.json'

Directory.Build.props

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
</PropertyGroup>
77

88
<PropertyGroup>
9-
<Version>1.0.0</Version>
10-
<PackageVersion>1.0.0</PackageVersion>
9+
<Version>2.0.0</Version>
1110
</PropertyGroup>
1211

1312
<PropertyGroup>

Directory.Packages.props

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<Project>
22
<ItemGroup>
3+
<PackageVersion Include="Autofac" Version="4.0.0" />
34
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.2.2" />
45
<PackageVersion Include="coverlet.collector" Version="6.0.0" />
56
<PackageVersion Include="FluentAssertions" Version="6.12.0" />

ReflectionEventing.sln

+12
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1717
README.md = README.md
1818
EndProjectSection
1919
EndProject
20+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReflectionEventing.Autofac", "src\ReflectionEventing.Autofac\ReflectionEventing.Autofac.csproj", "{6023E50F-2B4D-4315-B85D-9E8A12746045}"
21+
EndProject
22+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReflectionEventing.DependencyInjection", "src\ReflectionEventing.DependencyInjection\ReflectionEventing.DependencyInjection.csproj", "{09F0D6A2-3791-4173-A612-98E6EA92FCC4}"
23+
EndProject
2024
Global
2125
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2226
Debug|Any CPU = Debug|Any CPU
@@ -31,6 +35,14 @@ Global
3135
{898865CB-C39C-4E69-9FF8-E96AAD7FF0A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
3236
{898865CB-C39C-4E69-9FF8-E96AAD7FF0A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
3337
{898865CB-C39C-4E69-9FF8-E96AAD7FF0A4}.Release|Any CPU.Build.0 = Release|Any CPU
38+
{6023E50F-2B4D-4315-B85D-9E8A12746045}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39+
{6023E50F-2B4D-4315-B85D-9E8A12746045}.Debug|Any CPU.Build.0 = Debug|Any CPU
40+
{6023E50F-2B4D-4315-B85D-9E8A12746045}.Release|Any CPU.ActiveCfg = Release|Any CPU
41+
{6023E50F-2B4D-4315-B85D-9E8A12746045}.Release|Any CPU.Build.0 = Release|Any CPU
42+
{09F0D6A2-3791-4173-A612-98E6EA92FCC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43+
{09F0D6A2-3791-4173-A612-98E6EA92FCC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
44+
{09F0D6A2-3791-4173-A612-98E6EA92FCC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
45+
{09F0D6A2-3791-4173-A612-98E6EA92FCC4}.Release|Any CPU.Build.0 = Release|Any CPU
3446
EndGlobalSection
3547
GlobalSection(SolutionProperties) = preSolution
3648
HideSolutionNode = FALSE
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// This Source Code Form is subject to the terms of the MIT License.
2+
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
3+
// Copyright (C) Leszek Pomianowski and ReflectionEventing Contributors.
4+
// All Rights Reserved.
5+
6+
using System;
7+
using System.Collections.Generic;
8+
using Autofac;
9+
10+
namespace ReflectionEventing.Autofac;
11+
12+
public class AutofacConsumerProvider(ILifetimeScope lifetimeScope) : IConsumerProvider
13+
{
14+
public IEnumerable<object> GetConsumerTypes(Type consumerType)
15+
{
16+
if (consumerType is null)
17+
{
18+
throw new ArgumentNullException(nameof(consumerType));
19+
}
20+
21+
return new List<object> { lifetimeScope.Resolve(consumerType) };
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// This Source Code Form is subject to the terms of the MIT License.
2+
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
3+
// Copyright (C) Leszek Pomianowski and ReflectionEventing Contributors.
4+
// All Rights Reserved.
5+
6+
using Autofac;
7+
8+
namespace ReflectionEventing.Autofac;
9+
10+
public class AutofacEventBusBuilder(ContainerBuilder builder) : EventBusBuilder;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// This Source Code Form is subject to the terms of the MIT License.
2+
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
3+
// Copyright (C) Leszek Pomianowski and ReflectionEventing Contributors.
4+
// All Rights Reserved.
5+
6+
using System;
7+
using Autofac;
8+
9+
namespace ReflectionEventing.Autofac;
10+
11+
public static class ContainerBuilderExtensions
12+
{
13+
public static ContainerBuilder AddEventBus(
14+
this ContainerBuilder builder,
15+
Action<EventBusBuilder> configure
16+
)
17+
{
18+
AutofacEventBusBuilder autofacBuilder = new(builder);
19+
20+
configure(autofacBuilder);
21+
22+
_ = builder
23+
.RegisterType<HashedConsumerTypesProvider>()
24+
.As<IConsumerTypesProvider>()
25+
.WithParameter("consumers", autofacBuilder.GetConsumers())
26+
.SingleInstance();
27+
28+
_ = builder
29+
.RegisterType<AutofacConsumerProvider>()
30+
.As<IConsumerProvider>()
31+
.InstancePerLifetimeScope();
32+
33+
_ = builder.RegisterType<EventBus>().As<IEventBus>().InstancePerLifetimeScope();
34+
35+
return builder;
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<PackageId>ReflectionEventing.Autofac</PackageId>
5+
<TargetFrameworks>netstandard2.0;netstandard2.1;net462;net6.0;net8.0</TargetFrameworks>
6+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
7+
<IsTrimmable>true</IsTrimmable>
8+
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
9+
</PropertyGroup>
10+
11+
<PropertyGroup Condition="'$(TargetFramework)' == 'net8.0'">
12+
<PublishAot>true</PublishAot>
13+
<StripSymbols>true</StripSymbols>
14+
<OptimizationPreference>Speed</OptimizationPreference>
15+
</PropertyGroup>
16+
17+
<!-- Necessary polyfills -->
18+
<PropertyGroup>
19+
<PolySharpIncludeGeneratedTypes>
20+
System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute;
21+
System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute;
22+
System.Diagnostics.CodeAnalysis.MemberNotNullAttribute;
23+
System.Diagnostics.CodeAnalysis.NotNullAttribute;
24+
System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute;
25+
System.Diagnostics.CodeAnalysis.NotNullWhenAttribute;
26+
System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute;
27+
System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute;
28+
System.Runtime.CompilerServices.CallerArgumentExpressionAttribute;
29+
System.Runtime.CompilerServices.IsExternalInit;
30+
System.Runtime.CompilerServices.SkipLocalsInitAttribute;
31+
</PolySharpIncludeGeneratedTypes>
32+
</PropertyGroup>
33+
34+
<ItemGroup>
35+
<PackageReference Include="Autofac" />
36+
</ItemGroup>
37+
38+
<ItemGroup>
39+
<ProjectReference Include="..\ReflectionEventing\ReflectionEventing.csproj" />
40+
</ItemGroup>
41+
42+
</Project>

src/ReflectionEventing.Demo.Wpf/App.xaml.cs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
using ReflectionEventing.Demo.Wpf.Services;
77
using ReflectionEventing.Demo.Wpf.ViewModels;
8+
using ReflectionEventing.DependencyInjection;
89

910
namespace ReflectionEventing.Demo.Wpf;
1011

src/ReflectionEventing.Demo.Wpf/ReflectionEventing.Demo.Wpf.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
</ItemGroup>
1414

1515
<ItemGroup>
16-
<ProjectReference Include="..\ReflectionEventing\ReflectionEventing.csproj" />
16+
<ProjectReference Include="..\ReflectionEventing.DependencyInjection\ReflectionEventing.DependencyInjection.csproj" />
1717
</ItemGroup>
1818

1919
<ItemGroup>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// This Source Code Form is subject to the terms of the MIT License.
2+
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
3+
// Copyright (C) Leszek Pomianowski and ReflectionEventing Contributors.
4+
// All Rights Reserved.
5+
6+
namespace ReflectionEventing.DependencyInjection;
7+
8+
public class DependencyInjectionConsumerProvider(IServiceProvider serviceProvider)
9+
: IConsumerProvider
10+
{
11+
public IEnumerable<object> GetConsumerTypes(Type consumerType)
12+
{
13+
if (consumerType is null)
14+
{
15+
throw new ArgumentNullException(nameof(consumerType));
16+
}
17+
18+
IServiceScopeFactory? scopeFactory = serviceProvider.GetService<IServiceScopeFactory>();
19+
20+
if (scopeFactory is null)
21+
{
22+
return GetConsumersFromComputedScope(consumerType);
23+
}
24+
25+
return serviceProvider.GetServices(consumerType);
26+
}
27+
28+
private IEnumerable<object> GetConsumersFromComputedScope(Type consumerType)
29+
{
30+
using IServiceScope scope = serviceProvider.CreateScope();
31+
return scope.ServiceProvider.GetServices(consumerType);
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// This Source Code Form is subject to the terms of the MIT License.
2+
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
3+
// Copyright (C) Leszek Pomianowski and ReflectionEventing Contributors.
4+
// All Rights Reserved.
5+
6+
using System.Diagnostics.CodeAnalysis;
7+
8+
namespace ReflectionEventing.DependencyInjection;
9+
10+
public class DependencyInjectionEventBusBuilder(IServiceCollection services) : EventBusBuilder
11+
{
12+
public override void AddConsumer(
13+
#if NET5_0_OR_GREATER
14+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
15+
#endif
16+
Type consumerType
17+
)
18+
{
19+
ServiceDescriptor? descriptor = services.FirstOrDefault(d => d.ServiceType == consumerType);
20+
21+
if (descriptor is null)
22+
{
23+
throw new InvalidOperationException(
24+
"Event consumer must be registered in the service collection."
25+
);
26+
}
27+
28+
if (descriptor.Lifetime == ServiceLifetime.Transient)
29+
{
30+
throw new InvalidOperationException("Transient consumers are not supported.");
31+
}
32+
33+
base.AddConsumer(consumerType);
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// This Source Code Form is subject to the terms of the MIT License.
2+
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
3+
// Copyright (C) Leszek Pomianowski and ReflectionEventing Contributors.
4+
// All Rights Reserved.
5+
6+
global using System;
7+
global using System.Collections.Generic;
8+
global using System.Linq;
9+
global using System.Threading;
10+
global using System.Threading.Tasks;
11+
global using Microsoft.Extensions.DependencyInjection;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<PackageId>ReflectionEventing.DependencyInjection</PackageId>
5+
<TargetFrameworks>netstandard2.0;netstandard2.1;net462;net6.0;net8.0</TargetFrameworks>
6+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
7+
<IsTrimmable>true</IsTrimmable>
8+
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
9+
</PropertyGroup>
10+
11+
<PropertyGroup Condition="'$(TargetFramework)' == 'net8.0'">
12+
<PublishAot>true</PublishAot>
13+
<StripSymbols>true</StripSymbols>
14+
<OptimizationPreference>Speed</OptimizationPreference>
15+
</PropertyGroup>
16+
17+
<!-- Necessary polyfills -->
18+
<PropertyGroup>
19+
<PolySharpIncludeGeneratedTypes>
20+
System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute;
21+
System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute;
22+
System.Diagnostics.CodeAnalysis.MemberNotNullAttribute;
23+
System.Diagnostics.CodeAnalysis.NotNullAttribute;
24+
System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute;
25+
System.Diagnostics.CodeAnalysis.NotNullWhenAttribute;
26+
System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute;
27+
System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute;
28+
System.Runtime.CompilerServices.CallerArgumentExpressionAttribute;
29+
System.Runtime.CompilerServices.IsExternalInit;
30+
System.Runtime.CompilerServices.SkipLocalsInitAttribute;
31+
</PolySharpIncludeGeneratedTypes>
32+
</PropertyGroup>
33+
34+
<ItemGroup>
35+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
36+
</ItemGroup>
37+
38+
<ItemGroup>
39+
<ProjectReference Include="..\ReflectionEventing\ReflectionEventing.csproj" />
40+
</ItemGroup>
41+
42+
</Project>

src/ReflectionEventing/ServiceCollectionExtensions.cs src/ReflectionEventing.DependencyInjection/ServiceCollectionExtensions.cs

+6-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Copyright (C) Leszek Pomianowski and ReflectionEventing Contributors.
44
// All Rights Reserved.
55

6-
namespace ReflectionEventing;
6+
namespace ReflectionEventing.DependencyInjection;
77

88
/// <summary>
99
/// Provides extension methods for the <see cref="IServiceCollection"/> interface.
@@ -17,21 +17,22 @@ public static class ServiceCollectionExtensions
1717
/// <param name="configure">A delegate that configures the <see cref="EventBusBuilder"/>.</param>
1818
/// <returns>The same service collection so that multiple calls can be chained.</returns>
1919
/// <remarks>
20-
/// This method adds a singleton service of type <see cref="IConsumerProvider"/> that uses a <see cref="StaticConsumerProvider"/> with the consumers from the event bus builder.
20+
/// This method adds a singleton service of type <see cref="IConsumerTypesProvider"/> that uses a <see cref="HashedConsumerTypesProvider"/> with the consumers from the event bus builder.
2121
/// It also adds a scoped service of type <see cref="IEventBus"/> that uses the <see cref="EventBus"/> class.
2222
/// </remarks>
2323
public static IServiceCollection AddEventBus(
2424
this IServiceCollection services,
2525
Action<EventBusBuilder> configure
2626
)
2727
{
28-
EventBusBuilder builder = new(services);
28+
DependencyInjectionEventBusBuilder builder = new(services);
2929

3030
configure(builder);
3131

32-
_ = services.AddSingleton<IConsumerProvider>(
33-
new StaticConsumerProvider(builder.GetConsumers())
32+
_ = services.AddSingleton<IConsumerTypesProvider>(
33+
new HashedConsumerTypesProvider(builder.GetConsumers())
3434
);
35+
_ = services.AddScoped<IConsumerProvider, DependencyInjectionConsumerProvider>();
3536
_ = services.AddScoped<IEventBus, EventBus>();
3637

3738
return services;

0 commit comments

Comments
 (0)