Skip to content

Same di service provider is registered with Visual Studio for all MicrosoftDIToolkitPackage derivations ! #13

@tonyhallett

Description

@tonyhallett

[ProvideService(typeof(SToolkitServiceProvider<>), IsAsyncQueryable = true)]

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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions