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.
User contributions licensed under CC BY-SA 3.0