Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
tonyhallett opened this issue Oct 17, 2023 · 0 comments

Comments

@tonyhallett
Copy link

[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 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant