I am using autofac to inject depency injection in .net core based wpf mvvm project

-1
I have used same code in ASP.NET Core and it works fine. But I am facing issue in .NET Core based WPF MVVM solution.

.As usual, my project also start from below point. App.xaml.cs

public partial class App : Application
    {
        public IServiceProvider ServiceProvider { get; private set; }

        public IConfiguration Configuration { get; private set; }

    protected override void OnStartup(StartupEventArgs e)
    {
        var builder = new ConfigurationBuilder()
     .SetBasePath(Directory.GetCurrentDirectory())
  .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

        Configuration = builder.Build();

        var serviceCollection = new ServiceCollection();
        ConfigureServices(serviceCollection);

        ServiceProvider = serviceCollection.BuildServiceProvider();

        var loginWindow = ServiceProvider.GetRequiredService<Login>();

        loginWindow.Show();
    }

  private IServiceProvider ConfigureServices(IServiceCollection services)
        {                
            services.AddTransient(typeof(Login));
            services.AddDBObjectContext();    
            return services.ConfigureApplicationServices(Configuration);
        }
}

ServiceCollectionExtensions.cs

public static class ServiceCollectionExtensions
    {        
        public static IServiceProvider ConfigureApplicationServices(this 
  IServiceCollection services, IConfiguration configuration)
        {                
           var engine = EngineContext.Create();
           engine.Initialize(services);
 var serviceProvider = engine.ConfigureServices(services, configuration);

            return serviceProvider;
        }

public static void AddDBObjectContext(this IServiceCollection services)
        {
            services.AddDbContext<DBObjectContext>(optionsBuilder =>
            {
                optionsBuilder.UseSqlServerWithLazyLoading(services);
            });
        }    
    }

public class EngineContext
{        
    [MethodImpl(MethodImplOptions.Synchronized)]
    public static IEngine Create()
    {
        //create AppEngine as engine
        return Singleton<IEngine>.Instance ?? (Singleton<IEngine>.Instance 
      = new AppEngine());
    }

    public static void Replace(IEngine engine)
    {
        Singleton<IEngine>.Instance = engine;
    }

    public static IEngine Current
    {
        get
        {
            if (Singleton<IEngine>.Instance == null)
            {
                Create();
            }

            return Singleton<IEngine>.Instance;
        }
    }
}

AppEngine.cs File

public class AppEngine : IEngine    {
private IServiceProvider _serviceProvider { get; set; }
protected IServiceProvider GetServiceProvider()
        {            return ServiceProvider;        }

protected virtual IServiceProvider 
RegisterDependencies(IServiceCollection services, ITypeFinder typeFinder)        
{
                var containerBuilder = new ContainerBuilder();
                containerBuilder.RegisterInstance(this).As<IEngine> 
 ().SingleInstance();


containerBuilder.RegisterInstance(typeFinder).As<ITypeFinder> 
().SingleInstance();
                var dependencyRegistrars = 
typeFinder.FindClassesOfType<IDependencyRegistrar>();

var instances = dependencyRegistrars.Select(dependencyRegistrar => 
(IDependencyRegistrar)Activator.CreateInstance(dependencyRegistrar))                
.OrderBy(dependencyRegistrar => dependencyRegistrar.Order);
                foreach (var dependencyRegistrar in instances)                
dependencyRegistrar.Register(containerBuilder, typeFinder, config);

//populate Autofac container builder with the set of registered service descriptors
containerBuilder.Populate(services);

            //create service provider
_serviceProvider = new AutofacServiceProvider(containerBuilder.Build());
            return _serviceProvider;
        }

public IServiceProvider ConfigureServices(IServiceCollection services, 
IConfiguration configuration)        {           
            RegisterDependencies(services, typeFinder);
            return _serviceProvider;
        }
        public virtual IServiceProvider ServiceProvider => 
 _serviceProvider;
    }

interface IEngine.cs

public interface IEngine
    {            
        IServiceProvider ConfigureServices(IServiceCollection services, 
IConfiguration configuration);  
}

I don't have any issue in registering service, viewmodels, DBContextObject.

var loginWindow = ServiceProvider.GetRequiredService<Login>();            
            loginWindow.Show();

above line open login window which take to its constructor where LoginViewModel is resolved to assign DataContext as shown in below lines.

public Login()
        {
            InitializeComponent();
            this.Height = 425;
            this.Width = 550;
            tbxUserName.Focus();
     lblAttempt.Content = "Remaining Attempt: " + attemptCount.ToString();

      this.DataContext = EngineContext.Current.Resolve<LoginViewModel>();
        }

public partial class LoginViewModel
{
    #region Fields
    private readonly IUserService _userService;
    #endregion

    public LoginViewModel(IUserService userService)
    {
        this._userService = userService;
    }
 }

Here UserService is injected as DI in LoginViewModel constructor. In debugging mode, As I reached to below line in Login Constructor

this.DataContext = EngineContext.Current.Resolve<LoginViewModel>(); 

, it takes control to constructor of DBObjectContext.cs file.

public partial class DBObjectContext : DbContext, IDbContext
{
public DBObjectContext (DbContextOptions<DBObjectContext > options) : 
 base(options)
    {
    }
}

, it throws below error. As I remove UserService from LoginViewModel constructor, it works fine but with interaction with database.

Autofac.Core.DependencyResolutionException
  HResult=0x80131500
  Message=An error occurred during the activation of a particular registration. See the inner exception for details. Registration: 
Activator = ILoggerFactory (DelegateActivator), Services = [Microsoft.Extensions.Logging.ILoggerFactory], 
Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = Shared, Ownership = OwnedByLifetimeScope
  Source=Autofac
  StackTrace:
   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters, Object& decoratorTarget)
   at Autofac.Core.Resolving.InstanceLookup.<>c__DisplayClass5_0.<Execute>b__0()
   at Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(Guid id, Func`1 creator)
   at Autofac.Core.Resolving.InstanceLookup.Execute()
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)
   at Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType)
   at Autofac.Extensions.DependencyInjection.AutofacServiceProvider.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.Internal.ScopedLoggerFactory.Create(IServiceProvider internalServiceProvider, IDbContextOptions contextOptions)
   at Microsoft.EntityFrameworkCore.Internal.ServiceProviderCache.<>c__DisplayClass4_0.<GetOrAdd>g__BuildServiceProvider|0()
   at Microsoft.EntityFrameworkCore.Internal.ServiceProviderCache.<>c__DisplayClass4_0.<GetOrAdd>b__3(Int64 k)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.Internal.ServiceProviderCache.GetOrAdd(IDbContextOptions options, Boolean providerRequired)
   at Microsoft.EntityFrameworkCore.DbContext..ctor(DbContextOptions options)
   at wpfnet.Data.wpfnetObjectContext..ctor(DbContextOptions`1 options) in D:\wpfnet\wpfnet.Data\wpfnetObjectContext.cs:line 19
   at wpfnet.Framework.Infrastructure.DependencyRegistrar.<>c.<Register>b__0_1(IComponentContext context) in D:\wpfnet\wpfnet.Framework\Infrastructure\DependencyRegistrar.cs:line 40
   at Autofac.RegistrationExtensions.<>c__DisplayClass5_0`1.<Register>b__0(IComponentContext c, IEnumerable`1 p)
   at Autofac.Builder.RegistrationBuilder.<>c__DisplayClass0_0`1.<ForDelegate>b__0(IComponentContext c, IEnumerable`1 p)
   at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters, Object& decoratorTarget)

Inner Exception 1:
DependencyResolutionException: An error occurred during the activation of a particular registration. 
See the inner exception for details. Registration: Activator = IDbContextOptions (DelegateActivator), 
Services = [Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions], 
Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = Shared, Ownership = OwnedByLifetimeScope

Inner Exception 2:
DependencyResolutionException: A delegate registered to create instances of 
'Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptions' returned null.
wpf
mvvm
autofac
asked on Stack Overflow Oct 24, 2019 by Mohammad Bin Qasim Niaz • edited Oct 25, 2019 by Mohammad Bin Qasim Niaz

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0