Skip to content

Commit 1d26dbb

Browse files
committed
Initial commit: BeyondNetCode.Shell.Factory library
Extracted from beyondnetcode/ums - Namespace renamed: Ums.Shell.Factory -> BeyondNetCode.Shell.Factory - Package IDs updated for NuGet: BeyondNetCode.* - GitFlow workflow, CONTRIBUTING.md, VERSIONING.md added - All tests passing (2 tests) Original code authorship: raulnq (https://github.com/raulnq) Based on: csdevlib/factory-pattern (https://github.com/csdevlib/factory-pattern)
0 parents  commit 1d26dbb

48 files changed

Lines changed: 1705 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build.yml

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
name: CI / CD
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main, develop]
8+
tags:
9+
- 'v*'
10+
11+
env:
12+
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
13+
DOTNET_NOLOGO: true
14+
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
15+
16+
jobs:
17+
build-and-test:
18+
name: Build & Test (${{ matrix.os }})
19+
runs-on: ${{ matrix.os }}
20+
strategy:
21+
matrix:
22+
os: [ubuntu-latest, windows-latest]
23+
24+
steps:
25+
- name: Checkout
26+
uses: actions/checkout@v4
27+
with:
28+
fetch-depth: 0
29+
30+
- name: Setup .NET
31+
uses: actions/setup-dotnet@v5
32+
with:
33+
dotnet-version: 10.0.x
34+
35+
- name: Cache NuGet packages
36+
uses: actions/cache@v4
37+
with:
38+
path: ${{ env.NUGET_PACKAGES }}
39+
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
40+
restore-keys: ${{ runner.os }}-nuget-
41+
42+
- name: Restore
43+
run: dotnet restore BeyondNet.Factory.sln
44+
45+
- name: Build
46+
run: dotnet build BeyondNet.Factory.sln --configuration Release --no-restore
47+
48+
- name: Test
49+
run: dotnet test BeyondNet.Factory.sln --configuration Release --no-build --logger "trx;LogFileName=results.trx"
50+
51+
- name: Upload test results
52+
uses: actions/upload-artifact@v4
53+
if: always()
54+
with:
55+
name: test-results-${{ matrix.os }}
56+
path: "**/*.trx"
57+
58+
version:
59+
name: Determine Version
60+
runs-on: ubuntu-latest
61+
needs: build-and-test
62+
if: github.event_name == 'push' || github.event_name == 'tag'
63+
outputs:
64+
version: ${{ steps.version.outputs.version }}
65+
is_release: ${{ steps.version.outputs.is_release }}
66+
steps:
67+
- name: Checkout
68+
uses: actions/checkout@v4
69+
70+
- name: Get version from tag
71+
id: version
72+
run: |
73+
TAG="${GITHUB_REF#refs/tags/}"
74+
if [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-.*)?$ ]]; then
75+
VERSION="${TAG#v}"
76+
echo "version=$VERSION" >> $GITHUB_OUTPUT
77+
echo "is_release=true" >> $GITHUB_OUTPUT
78+
else
79+
HASH="${GITHUB_SHA:0:7}"
80+
BRANCH_NAME="${GITHUB_REF#refs/heads/}"
81+
echo "version=0.0.0-$BRANCH_NAME+$HASH" >> $GITHUB_OUTPUT
82+
echo "is_release=false" >> $GITHUB_OUTPUT
83+
fi
84+
85+
pack:
86+
name: Pack NuGet Packages
87+
runs-on: ubuntu-latest
88+
needs: [build-and-test, version]
89+
if: needs.version.outputs.is_release == 'true'
90+
strategy:
91+
matrix:
92+
project:
93+
- src/BeyondNetCode.Shell.Factory/BeyondNetCode.Shell.Factory.csproj
94+
- src/BeyondNetCode.Shell.Factory.Installer/BeyondNetCode.Shell.Factory.Installer.csproj
95+
steps:
96+
- uses: actions/checkout@v4
97+
98+
- name: Setup .NET
99+
uses: actions/setup-dotnet@v5
100+
with:
101+
dotnet-version: 10.0.x
102+
103+
- name: Pack
104+
run: |
105+
dotnet pack "${{ matrix.project }}" \
106+
-c Release \
107+
--version:${{ needs.version.outputs.version }} \
108+
--no-build \
109+
-p:PackageOutputPath=${{ github.workspace }}/nupkgs
110+
111+
- name: Upload artifacts
112+
uses: actions/upload-artifact@v4
113+
with:
114+
name: packages-${{ matrix.project }}
115+
path: nupkgs/*.nupkg
116+
117+
publish:
118+
name: Publish to NuGet
119+
runs-on: ubuntu-latest
120+
needs: pack
121+
if: needs.pack.result == 'success' && needs.version.outputs.is_release == 'true'
122+
environment: nuget-release
123+
124+
steps:
125+
- name: Download packages
126+
uses: actions/download-artifact@v4
127+
with:
128+
pattern: packages-*
129+
path: ./nupkgs
130+
merge-multiple: true
131+
132+
- name: Setup .NET
133+
uses: actions/setup-dotnet@v5
134+
with:
135+
dotnet-version: 10.0.x
136+
137+
- name: Push to NuGet.org
138+
run: |
139+
for nupkg in $(find ./nupkgs -name '*.nupkg'); do
140+
dotnet nuget push "$nupkg" \
141+
--api-key ${{ secrets.NUGET_API_KEY }} \
142+
--source https://api.nuget.org/v3/index.json \
143+
--skip-duplicate
144+
done
145+
env:
146+
DOTNET_CLI_TELEMETRY_OPTOUT: '1'
147+
148+
release:
149+
name: Create GitHub Release
150+
runs-on: ubuntu-latest
151+
needs: [version]
152+
if: needs.version.outputs.is_release == 'true'
153+
steps:
154+
- uses: actions/checkout@v4
155+
156+
- name: Generate Release Notes
157+
id: release-notes
158+
uses: actions/github-script@v7
159+
with:
160+
script: |
161+
const { data: commits } = await github.rest.repos.listCommits({
162+
owner: context.repo.owner,
163+
repo: context.repo.repo,
164+
per_page: 100,
165+
since: '2024-01-01'
166+
});
167+
let body = '## What\'s New\n\n';
168+
body += `**Version:** ${context.payload.ref.replace('refs/tags/', '')}\n\n`;
169+
body += '### Commits\n';
170+
commits.slice(0, 20).forEach(c => {
171+
body += `- ${c.commit.message.split('\n')[0]} (${c.sha.slice(0, 7)})\n`;
172+
});
173+
return body;
174+
175+
- name: Create Release
176+
uses: softprops/action-gh-release@v2
177+
with:
178+
tag_name: ${{ github.ref_name }}
179+
name: Release ${{ github.ref_name }}
180+
body: ${{ steps.release-notes.outputs.result }}
181+
draft: false
182+
prerelease: ${{ contains(needs.version.outputs.version, 'beta') || contains(needs.version.outputs.version, 'alpha') }}
183+
env:
184+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

BeyondNet.Factory.sln

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
Microsoft Visual Studio Solution File, Format Version 12.00
2+
# Visual Studio Version 17
3+
VisualStudioVersion = 17.0.31903.59
4+
MinimumVisualStudioVersion = 10.0.40219.1
5+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeyondNetCode.Shell.Factory", "BeyondNetCode.Shell.Factory\BeyondNetCode.Shell.Factory.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
6+
EndProject
7+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeyondNetCode.Shell.Factory.Installer", "BeyondNetCode.Shell.Factory.Installer\BeyondNetCode.Shell.Factory.Installer.csproj", "{B2C3D4E5-F6A7-8901-BCDE-F12345678901}"
8+
EndProject
9+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeyondNetCode.Shell.Factory.Tests", "BeyondNetCode.Shell.Factory.Tests\BeyondNetCode.Shell.Factory.Tests.csproj", "{C3D4E5F6-A7B8-9012-CDEF-123456789012}"
10+
EndProject
11+
Global
12+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
13+
Debug|Any CPU = Debug|Any CPU
14+
Release|Any CPU = Release|Any CPU
15+
EndGlobalSection
16+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
17+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.Build.0 = Debug|Any CPU
19+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.ActiveCfg = Release|Any CPU
20+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.Build.0 = Release|Any CPU
21+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|Any CPU.Build.0 = Debug|Any CPU
23+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.ActiveCfg = Release|Any CPU
24+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.Build.0 = Release|Any CPU
25+
{C3D4E5F6-A7B8-9012-CDEF-123456789012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26+
{C3D4E5F6-A7B8-9012-CDEF-123456789012}.Debug|Any CPU.Build.0 = Debug|Any CPU
27+
{C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.ActiveCfg = Release|Any CPU
28+
{C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.Build.0 = Release|Any CPU
29+
EndGlobalSection
30+
GlobalSection(SolutionProperties) = preSolution
31+
HideSolutionNode = FALSE
32+
EndGlobalSection
33+
EndGlobal
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
<AssemblyName>BeyondNetCode.Shell.Factory.Installer</AssemblyName>
8+
<RootNamespace>BeyondNetCode.Shell.Factory.Installer</RootNamespace>
9+
<Title>BeyondNetCode.Shell.Factory.Installer</Title>
10+
<Description>BeyondNetCode.Shell.Factory.Installer provides installation and registration utilities for Shell.Factory components, enabling seamless integration with dependency injection containers.</Description>
11+
<Copyright>BeyondNet Code</Copyright>
12+
<RepositoryUrl>https://github.com/beyondnetcode/Shell.Factory</RepositoryUrl>
13+
<PackageProjectUrl>https://github.com/beyondnetcode/Shell.Factory</PackageProjectUrl>
14+
<Version>1.0.0</Version>
15+
<AssemblyVersion>1.0.0</AssemblyVersion>
16+
</PropertyGroup>
17+
18+
<ItemGroup>
19+
<None Include="../../../LICENSE">
20+
<Pack>True</Pack>
21+
<PackagePath>LICENSE</PackagePath>
22+
</None>
23+
<None Include="../../../README.md">
24+
<Pack>True</Pack>
25+
<PackagePath>README.md</PackagePath>
26+
</None>
27+
</ItemGroup>
28+
29+
<ItemGroup>
30+
<ProjectReference Include="../BeyondNetCode.Shell.Factory/BeyondNetCode.Shell.Factory.csproj" />
31+
</ItemGroup>
32+
33+
</Project>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using BeyondNetCode.Shell.Factory.Impl;
2+
using BeyondNetCode.Shell.Factory.Installer.Impl;
3+
using BeyondNetCode.Shell.Factory.Interfaces;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using Microsoft.Extensions.DependencyInjection.Extensions;
6+
7+
namespace BeyondNetCode.Shell.Factory.Installer.Extensions
8+
{
9+
public static class ServiceCollectionExtensions
10+
{
11+
/// <summary>
12+
/// Registers the factory infrastructure into the DI container.
13+
///
14+
/// <see cref="FactoryCreator"/> is wired with a <c>Func&lt;Type, object&gt;</c>
15+
/// that delegates to <see cref="IServiceProvider.GetRequiredService(Type)"/>.
16+
/// Every concrete implementation type that the factory may create must
17+
/// therefore be registered in the same DI container.
18+
/// </summary>
19+
public static IServiceCollection AddFactory(
20+
this IServiceCollection services,
21+
Action<IFactoryBuilder>? action = null)
22+
{
23+
// FactoryCreator receives a factory function backed by IServiceProvider.
24+
// This is the accepted pattern for generic object factories in .NET:
25+
// the factory is part of the composition root and is allowed to resolve
26+
// services by type.
27+
services.TryAddSingleton<IFactoryCreator>(sp =>
28+
new FactoryCreator(sp.GetRequiredService));
29+
30+
services.TryAddSingleton<IFactory, Factory.Impl.Factory>();
31+
32+
services.TryAddSingleton<IFactorySetupProvider, FactorySetupProvider>();
33+
34+
action?.Invoke(new FactoryBuilder(services));
35+
36+
return services;
37+
}
38+
}
39+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using BeyondNetCode.Shell.Factory.Interfaces;
2+
using Microsoft.Extensions.DependencyInjection;
3+
4+
namespace BeyondNetCode.Shell.Factory.Installer.Extensions
5+
{
6+
public static class ServiceProviderExtensions
7+
{
8+
public static IFactory GetFactory(this IServiceProvider provider)
9+
{
10+
return provider.GetService<IFactory>();
11+
}
12+
}
13+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace BeyondNetCode.Shell.Factory.Installer
8+
{
9+
internal class GlobalUsings
10+
{
11+
}
12+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using BeyondNetCode.Shell.Factory.Interfaces;
2+
using Microsoft.Extensions.DependencyInjection;
3+
4+
namespace BeyondNetCode.Shell.Factory.Installer.Impl
5+
{
6+
public class FactoryBuilder : IFactoryBuilder
7+
{
8+
private readonly IServiceCollection _serviceCollection;
9+
10+
public FactoryBuilder(IServiceCollection serviceCollection)
11+
{
12+
_serviceCollection = serviceCollection;
13+
}
14+
15+
public IFactoryBuilder AddSingleton<TService, TImplementation>()
16+
where TService : class
17+
where TImplementation : class, TService
18+
{
19+
_serviceCollection.AddSingleton<TService, TImplementation>();
20+
21+
return this;
22+
}
23+
24+
public IFactoryBuilder AddTransient<TService, TImplementation>()
25+
where TService : class
26+
where TImplementation : class, TService
27+
{
28+
_serviceCollection.AddTransient<TService, TImplementation>();
29+
30+
return this;
31+
}
32+
33+
public IFactoryBuilder AddSource<TImplementation>() where TImplementation : class, IFactorySetupSource
34+
{
35+
_serviceCollection.AddSingleton<IFactorySetupSource, TImplementation>();
36+
37+
return this;
38+
}
39+
}
40+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
<AssemblyName>BeyondNetCode.Shell.Factory.Tests</AssemblyName>
8+
<RootNamespace>BeyondNetCode.Shell.Factory.Tests</RootNamespace>
9+
<IsPackable>false</IsPackable>
10+
<IsTestProject>true</IsTestProject>
11+
</PropertyGroup>
12+
13+
<ItemGroup>
14+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
15+
<PackageReference Include="MSTest.TestAdapter" Version="3.0.4" />
16+
<PackageReference Include="MSTest.TestFramework" Version="3.0.4" />
17+
<PackageReference Include="coverlet.collector" Version="6.0.0" />
18+
<PackageReference Include="Shouldly" Version="4.2.1" />
19+
</ItemGroup>
20+
21+
<ItemGroup>
22+
<ProjectReference Include="../BeyondNetCode.Shell.Factory/BeyondNetCode.Shell.Factory.csproj" />
23+
</ItemGroup>
24+
25+
</Project>

0 commit comments

Comments
 (0)