-
-
Notifications
You must be signed in to change notification settings - Fork 146
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement Core & Plugin Service Collection (#129)
- Loading branch information
1 parent
8d1891a
commit 4e8c18a
Showing
35 changed files
with
999 additions
and
667 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
--- | ||
title: Dependency Injection | ||
description: How to make use of dependency injection in CounterStrikeSharp | ||
sidebar: | ||
order: 1 | ||
--- | ||
|
||
`CounterStrikeSharp` uses a standard <a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-8.0" target="_blank">`IServiceCollection`</a> to allow for dependency injection in plugins. | ||
|
||
There are a handful of standard services that are predefined for you (`ILogger` for logging for instance), with more to come in the future. To add your own scoped & singleton services to the container, you can create a new class that implements the `IPluginServiceCollection<T>` interface for your plugin. | ||
|
||
```csharp | ||
public class TestPlugin : BasePlugin | ||
{ | ||
// Plugin code... | ||
} | ||
|
||
public class TestPluginServiceCollection : IPluginServiceCollection<TestPlugin> | ||
{ | ||
public void ConfigureServices(IServiceCollection serviceCollection) | ||
{ | ||
serviceCollection.AddScoped<ExampleInjectedClass>(); | ||
serviceCollection.AddLogging(builder => ...); | ||
} | ||
} | ||
``` | ||
|
||
CounterStrikeSharp will search your assembly for any implementations of `IPlugin` and then any implementations of `IPluginServiceCollection<T>` where `T` is your plugin. It will then configure the service provider and then request a singleton instance of your plugin before proceeding to the load step. | ||
|
||
In this way, any dependencies that are listed in your plugin class constructor will automatically get injected at instantation time (before load). | ||
|
||
### Example | ||
|
||
```csharp | ||
public class TestInjectedClass | ||
{ | ||
private readonly ILogger<TestInjectedClass> _logger; | ||
|
||
public TestInjectedClass(ILogger<TestInjectedClass> logger) | ||
{ | ||
_logger = logger; | ||
} | ||
|
||
public void Hello() | ||
{ | ||
_logger.LogInformation("Hello World from Test Injected Class"); | ||
} | ||
} | ||
|
||
public class TestPluginServiceCollection : IPluginServiceCollection<SamplePlugin> | ||
{ | ||
public void ConfigureServices(IServiceCollection serviceCollection) | ||
{ | ||
serviceCollection.AddScoped<TestInjectedClass>(); | ||
} | ||
} | ||
|
||
public class SamplePlugin : BasePlugin | ||
{ | ||
private readonly TestInjectedClass _testInjectedClass; | ||
public SamplePlugin(TestInjectedClass testInjectedClass) | ||
{ | ||
_testInjectedClass = testInjectedClass; | ||
} | ||
|
||
public override void Load(bool hotReload) | ||
{ | ||
_testInjectedClass.Hello(); | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
using System; | ||
using System.IO; | ||
using System.Reflection; | ||
using System.Runtime.InteropServices; | ||
using CounterStrikeSharp.API.Core; | ||
using CounterStrikeSharp.API.Core.Hosting; | ||
using CounterStrikeSharp.API.Core.Logging; | ||
using CounterStrikeSharp.API.Core.Plugin; | ||
using CounterStrikeSharp.API.Core.Plugin.Host; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Extensions.Logging; | ||
using Serilog; | ||
|
||
namespace CounterStrikeSharp.API; | ||
|
||
public static class Bootstrap | ||
{ | ||
[UnmanagedCallersOnly] | ||
// Used by .NET Host in C++ to initiate loading | ||
public static int Run() | ||
{ | ||
try | ||
{ | ||
// Path to /game/csgo/addons/counterstrikesharp | ||
var contentRoot = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.Parent.FullName; | ||
|
||
using var host = Host.CreateDefaultBuilder() | ||
.UseContentRoot(contentRoot) | ||
.ConfigureServices(services => | ||
{ | ||
services.AddLogging(builder => | ||
{ | ||
builder.ClearProviders(); | ||
builder.AddCoreLogging(contentRoot); | ||
}); | ||
|
||
services.AddSingleton<IScriptHostConfiguration, ScriptHostConfiguration>(); | ||
services.AddScoped<Application>(); | ||
services.AddSingleton<IPluginManager, PluginManager>(); | ||
services.AddScoped<IPluginContextQueryHandler, PluginContextQueryHandler>(); | ||
|
||
services.Scan(i => i.FromCallingAssembly() | ||
.AddClasses(c => c.AssignableTo<IStartupService>()) | ||
.AsSelfWithInterfaces() | ||
.WithSingletonLifetime()); | ||
}) | ||
.Build(); | ||
|
||
using IServiceScope scope = host.Services.CreateScope(); | ||
|
||
// TODO: Improve static singleton access | ||
GameData.GameDataProvider = scope.ServiceProvider.GetRequiredService<GameDataProvider>(); | ||
|
||
var application = scope.ServiceProvider.GetRequiredService<Application>(); | ||
application.Start(); | ||
|
||
return 1; | ||
} | ||
catch (Exception e) | ||
{ | ||
Console.Error.WriteLine(e); | ||
Log.Fatal(e, "Failed to start application"); | ||
return 0; | ||
} | ||
} | ||
} |
Oops, something went wrong.