// Add the IToolkitServiceProvider to the VS IServiceProvider
AsyncServiceCreatorCallback serviceCreatorCallback = (sc, ct, t) =>
{
return Task.FromResult((object)this.ServiceProvider);
};
AddService(typeof(SToolkitServiceProvider<TPackage>), serviceCreatorCallback, true);
The generic does not work.
-
Create two packages of this format. In one of them VS.GetRequiredService will throw as the IToolkitServiceProvider<TPackage> implementation will be for the other package.
public sealed class DIBroken1Package : MicrosoftDIToolkitPackage<DIBroken1Package>
{
protected override void InitializeServices(IServiceCollection services)
{
services.RegisterCommands(ServiceLifetime.Singleton);
services.AddSingleton<Dependency>();
}
internal static Dependency GetDependency()
{
var sp = VS.GetRequiredService<SToolkitServiceProvider<DIBroken1Package>, IToolkitServiceProvider<DIBroken1Package>>();
return sp.GetRequiredService<Dependency>();
}
}
internal class Dependency
{
public string Message { get; } = "Hello from Dependency";
}
[Command(PackageIds.MyCommand)]
internal sealed class MyCommand : BaseDICommand
{
public MyCommand(DIToolkitPackage package):base(package)
{
}
protected override async Task ExecuteAsync(OleMenuCmdEventArgs e)
{
var dependency = DIBroken1Package.GetDependency();
await VS.MessageBox.ShowAsync(dependency.Message);
}
}
A quick and dirty solution
public interface IToolkitServiceProviderContainer
{
IServiceProvider Get<TPackage>() where TPackage : AsyncPackage;
IServiceProvider Get(Type packageType);
}
public class ToolkitServiceProviderContainer : IToolkitServiceProviderContainer
{
private static Dictionary<Type, IServiceProvider> _serviceProviders = new Dictionary<Type, IServiceProvider>();
internal static void AddServiceProvider<TPackage>(IServiceProvider serviceProvider) where TPackage : AsyncPackage
{
_serviceProviders.Add(typeof(TPackage), serviceProvider);
}
public IServiceProvider Get<TPackage>() where TPackage : AsyncPackage
{
return this.Get(typeof(TPackage));
}
public IServiceProvider Get(Type packageType)
{
return _serviceProviders[packageType];
}
}
[ProvideService(typeof(SToolkitServiceProviderContainer), IsAsyncQueryable = true)]
public abstract class DIToolkitPackage<TPackage> : DIToolkitPackage
where TPackage : AsyncPackage
{
/// <summary>
/// Initializes the <see cref="AsyncPackage"/>
/// </summary>
/// <param name="cancellationToken"></param>
/// <param name="progress"></param>
/// <returns></returns>
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
// AS BEFORE
this.ServiceProvider = serviceProvider;
ToolkitServiceProviderContainer.AddServiceProvider<TPackage>(this.ServiceProvider);
// Add the IToolkitServiceProvider to the VS IServiceProvider
AsyncServiceCreatorCallback serviceCreatorCallback = (sc, ct, t) =>
{
if(t == typeof(SToolkitServiceProviderContainer))
{
return Task.FromResult((object)new ToolkitServiceProviderContainer());
}
return Task.FromResult<object?>(null);
};
AddService(typeof(SToolkitServiceProviderContainer), serviceCreatorCallback, true);
// AS BEFORE
}
Alternatively, just make the ServiceProvider property static ?
[ProvideService(typeof(SToolkitServiceProvider<>), IsAsyncQueryable = true)]
https://github.com/VsixCommunity/Community.VisualStudio.Toolkit.DependencyInjection/blob/639e8340345a0d528670b70f7817af662d64c01a/src/Core/Shared/DIToolkitPackage.cs#L49
The generic does not work.
- Create two packages of this format. In one of them VS.GetRequiredService will throw as the
IToolkitServiceProvider<TPackage>
implementation will be for the other package.A quick and dirty solution
Alternatively, just make the ServiceProvider property static ?