-
Notifications
You must be signed in to change notification settings - Fork 8
Open
Description
[ProvideService(typeof(SToolkitServiceProvider<>), IsAsyncQueryable = true)]
Community.VisualStudio.Toolkit.DependencyInjection/src/Core/Shared/DIToolkitPackage.cs
Line 49 in 639e834
| AddService(typeof(SToolkitServiceProvider<TPackage>), serviceCreatorCallback, true); |
// 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 ?
Metadata
Metadata
Assignees
Labels
No labels