How to resolve a named instance from a static class? - c#

Does anyone have any idea about what i doing wrong?
I have a such static class:
public static class ApplicationContainer
{
private static ContainerBuilder builder = null;
private static IContainer container = null;
public static void Create()
{
builder = new ContainerBuilder();
builder.RegisterInstance(new Repository<Log>(RepositoryType.Main))
.As<IRepository<Log>>().SingleInstance()
.Named("Log", typeof(Repository<Log>));
container = builder.Build();
}
public static IContainer Container()
{
if (container != null) return container;
throw new Exception("Container is not ready.");
}
}
In Global.asax.cs of my MVC application i have:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
ApplicationContainer.Create();
RegisterRoutes(RouteTable.Routes);
}
And now about problem: how can i to resolve named instance from a container?
public class DefaultLogger : ILogger
{
ApplicationContainer.Container().Resolve("Log", typeof(Repository<Log>);// <--- does not work
}
But when ApplicationContainer class is not static, resolving from container works very good.
I use autofac 2.2.4.

I believe you cannot compile this code since you are missing a closing ')' for your .Resolve(...) call.
That said, have you looked at the Autofac ASP.Net integration modules?

Related

Autofac Cannot resolve parameter serviceScopeFactory of constructor 'Void

I get the following error when I try to inject IServiceScopeFactory in a class in my business layer: "Cannot resolve parameter 'Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory' of constructor 'Void"
I havent worked with AutoFac before so I am wondering what I am missing:
This is my code:
private static void ConfigureAutoFacIoC(ContainerBuilder builder, HttpConfiguration config, IAppBuilder app)
{
AutoFacRegister.RegisterDependency(builder, Assembly.GetExecutingAssembly());
RegisterWebApiDependency(builder);
builder.RegisterWebApiFilterProvider(config);
var container = builder.Build();
// Set the dependency resolver to be Autofac.
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
}
public static class AutoFacRegister
{
public static void RegisterDependency(ContainerBuilder builder, Assembly webApiAssembly)
{
RegisterDataLayer(builder);
RegisterBusinessLayer(builder);
RegisterShared(builder);
RegisterPresentationLayer(builder, webApiAssembly);
}
private static void RegisterDataLayer(ContainerBuilder builder)
{
builder.RegisterType<SBSContext>().InstancePerLifetimeScope();
builder.RegisterType<AgdaContext>().InstancePerLifetimeScope();
builder.RegisterType<MailingRepository>().As<IMailingRepository>();
builder.RegisterType<MembershipRepository>().As<IMembershipRepository>();
builder.RegisterType<CourseMomentRepository>().As<ICourseMomentRepository>();
builder.RegisterType<MedalRepository>().As<IMedalRepository>();
builder.RegisterType<PersonRepository>().As<IPersonRepository>();
builder.RegisterType<CourseRepository>().As<ICourseRepository>();
builder.RegisterType<OrganisationRepository>().As<IOrganisationRepository>();
builder.RegisterType<FunctionRepository>().As<IFunctionRepository>();
builder.RegisterType<PaymentRepository>().As<IPaymentRepository>();
builder.RegisterType<ChargeCategoryRepository>().As<IChargeCategoryRepository>();
builder.RegisterType<OutcodeRepository>().As<IOutcodeRepository>();
builder.RegisterType<UserRepository>().As<IUserRepository>();
builder.RegisterType<ViewPersonRepository>().As<IViewPersonRepository>();
builder.RegisterType<AgdaRepository>().As<IAgdaRepository>();
builder.RegisterType<ReportRepository>().As<IReportRepository>();
builder.RegisterType<ReportManager>().As<IReportManager>();
builder.RegisterType<CourseApplicationRepository>().As<ICourseApplicationRepository>();
builder.RegisterType<RepdayRepository>().As<IRepdayRepository>();
builder.RegisterType<ChargeCategoryRepository>().As<IChargeCategoryRepository>();
builder.RegisterType<CommuneRepository>().As<ICommuneRepository>();
builder.RegisterType<PapApiAmbassador>().As<IPapApiAmbassador>();
builder.RegisterType<VolenteerRepository>().As<IVolenteerRepository>();
builder.RegisterType<AgreementTypeRepository>().As<IAgreementTypeRepository>();
builder.RegisterType<CourseMomentStatusRepository>().As<ICourseMomentStatusRepository>();
builder.RegisterType<CourseTypeRepository>().As<ICourseTypeRepository>();
builder.RegisterType<AttestationRepository>().As<IAttestationRepository>();
builder.RegisterGeneric(typeof(GenericRepository<,>)).As(typeof(IGenericRepository<,>));
}
private static void RegisterBusinessLayer(ContainerBuilder builder)
{
var bllAssembly = AppDomain.CurrentDomain.GetAssemblies().
SingleOrDefault(assembly => assembly.GetName().Name == "SBS.Ferdinand.BusinessLayer");
builder.RegisterAssemblyTypes(typeof(IServiceScopeFactory).Assembly).As<IServiceScopeFactory>();
builder.RegisterAssemblyTypes(bllAssembly)
.Where(x => x.Name.EndsWith("Handler"))
.AsImplementedInterfaces();
builder.RegisterAssemblyTypes(bllAssembly)
.Where(x => x.Name.EndsWith("Helper"))
.AsImplementedInterfaces()
.SingleInstance();
builder.RegisterType<OrganisationMigrator>().As<IOrganisationMigrator>();
}
private static void RegisterShared(ContainerBuilder builder)
{
builder.RegisterType<BaseRequestModel>().AsImplementedInterfaces().InstancePerLifetimeScope();
builder.RegisterType<ImpersonateUser>().As<IImpersonateUser>();
builder.RegisterModule<NLogModule>();
builder.RegisterType<ApiApplicationSettings>().As<IApiApplicationSettings>().SingleInstance();
}
private static void RegisterPresentationLayer(ContainerBuilder builder, Assembly webApiAssembly)
{
builder.RegisterApiControllers(webApiAssembly);
}
public static void RegisterHangfireDependency(ContainerBuilder builder)
{
RegisterDataLayer(builder);
RegisterBusinessLayer(builder);
RegisterShared(builder);
builder.RegisterType<CronJobManager>().As<ICronJobManager>().InstancePerLifetimeScope();
}
}
public class NLogModule : Autofac.Module
{
private static void OnComponentPreparing(object sender, PreparingEventArgs e)
{
e.Parameters = e.Parameters.Union(
new[]
{
new ResolvedParameter(
(p, i) => p.ParameterType == typeof (ILogger),
(p, i) => LogManager.GetLogger(p.Member.DeclaringType.FullName))
});
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
// Handle constructor parameters.
registration.Preparing += OnComponentPreparing;
}
}
where I try to inject the IServiceScopeFactory
public class PaymentHandler : IPaymentHandler
{
private readonly IServiceScopeFactory _serviceScopeFactory;
public PaymentHandler(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
}
}
It appears you're trying to kind of mix-and-match .NET 4.5 dependency injection (e.g., with the DependencyResolver mechanism in Web API) and new .NET Core dependency injection (e.g., IServiceProvider). The really short answer here is... you can't do that.
If you read the exception it tells you exactly what's missing:
Cannot resolve parameter 'Microsoft.Extensions.DependencyInjection.IServiceScopeFactory'
You have a constructor that takes an IServiceScopeFactory. You want Autofac to inject it. You didn't tell Autofac where to get it. No magic here: if you didn't register it with Autofac, Autofac's not going to be able to figure it out.
I'd guess what you want is the ability to create lifetime scopes inside that PaymentHandler. Since that's not really a thing in Web API with DependencyResolver, instead of trying to mix-and-match, you have to use Autofac directly.
Inject the ILifetimeScope instead.
public class PaymentHandler : IPaymentHandler
{
private readonly ILifetimeScope _scope;
public PaymentHandler(ILifetimeScope scope)
{
_scope = scope;
// now you can do
// using(var childScope = _scope.BeginLifetimeScope){ }
}
}
At this point, it'd be good to head over to the Autofac docs to learn more about lifetime scopes and how to work with them. But this should get you unblocked.

unity dependency error -make sure that the controller has a parameterless public constructor

Sorry i am new to IOC concepts. I have been trying to implement Unity.WebAPI (5.3.0.) in my web api project but getting following error;
An error occurred when trying to create a controller of type 'TransactionController'. Make sure that the controller has a parameterless public constructor
UnityResolver Class
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
container.Dispose();
}
}
Web Api Config
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<IFService, FService>(new HierarchicalLifetimeManager());
container.RegisterType<IMService, MService>(new HierarchicalLifetimeManager());
container.RegisterType<ITransactionService, TransactionService>(new HierarchicalLifetimeManager());
container.RegisterType<IMRepository, MRepository>();
config.DependencyResolver = new UnityResolver(container);
}
}
Global.asax
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Controller
public class TransactionController : ApiController
{
private readonly ITransactionService _transactionService;
private readonly IMService _mService;
/// <summary>
/// Public constructor to initialize transaction service instance
/// </summary>
public TransactionController(ITransactionService transactiontService, IMService mService)
{
_mService = mService;
_transactionService = transactiontService;
}
[HttpGet]
public IHttpActionResult IsApiAlive()
{
return Ok();
}
TransactionService Class constructor
private readonly IMRepository _mRepository;
public TransactionService(IMRepository mRepository)
{
_mRepository = mRepository;
}
Check to make sure that all dependencies for the object graphs have been registered so that they can be resolved correctly.
You are most likely missing a dependency registration.
For TransactionService, you are passing/injecting the implementations in the constructors
public TransactionService(MRepository mRepository, FService fService) {
_mRepository = mRepository;
_fservice = fService;
}
while you only registered the interfaces.
container.RegisterType<IFService, FService>(new HierarchicalLifetimeManager());
container.RegisterType<IMService, MService>(new HierarchicalLifetimeManager());
container.RegisterType<ITransactionService, TransactionService>(new HierarchicalLifetimeManager());
container.RegisterType<IMRepository, MRepository>();
The resolver will do the actual initialization and injection of the implementations based on the known dependencies.
Change
public TransactionService(MRepository mRepository, FService fService)
To rely on the registered interfaces
private readonly IMRepository mRepository;
private readonly IFService fService;
public TransactionService(IMRepository mRepository, IFService fService) {
this.mRepository = mRepository;
this.fservice = fService;
}
every class involved in creating/resolving the controller needs to be checked to make sure that their dependencies can be resolved without error.

Unity Dependency injection on the same project for web api and mvc

At first I started the project with asp.net mvc and unity.mvc for DI, then wanted to add web api to the same project and installed unity.webapi but with that now unity dependency injection is unable to inject service instances to the ApiControllers however the controller class are working.
UnityConfig.cs
public static class UnityConfig
{
private static Lazy<IUnityContainer> container =
new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer Container => container.Value;
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IEmployeeService, EmployeeService>();
container.RegisterType<IRepository<Employee>, Repository<Employee>>();
}
}
ApiController.cs
public class EmployeeApiController : ApiController
{
private readonly IEmployeeService _employeeService;
public EmployeeApiController(IEmployeeService employeeService)
{
_employeeService = employeeService;
}
public EmployeeApiController(){}
// GET: api/EmployeeApi
public IEnumerable<Employee> Get()
{
var a = _employeeService.GetAll();
return a;
}
}
Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
On the get action of apicontroller the IService throughs a null pointer exception.
Web API defines the following interfaces for resolving dependencies:
public interface IDependencyResolver : IDependencyScope, IDisposable
{
IDependencyScope BeginScope();
}
public interface IDependencyScope : IDisposable
{
object GetService(Type serviceType);
IEnumerable<object> GetServices(Type serviceType);
}
As you pointed out in your comment, the Unity.WebApi nuget package provides this implementation which you can just register in the application startup.
For full reference:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
UnityConfig.RegisterComponents();
}
}
Found the solution:
added the following line on the UnityConfig.cs:
public static void RegisterTypes(IUnityContainer container)
{
//Add this line
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
container.RegisterType<IEmployeeService, EmployeeService>();
container.RegisterType<IRepository<Employee>, Repository<Employee>>();
}

Creating actorRefs from ACtorSystem using DI() Extension, throws object reference exception

I am trying to setup a base project that will make use of Autofac for dependency injection.
I have the following problem, when trying to get an instance of my Actor doing the following:
_system = Akka.Actor.ActorSystem.Create(_settings.SystemName);
PingActor = _system.ActorOf(_system.DI().Props<PingActor>(), ActorNames.PingActor);
This throws an 'Object reference' exception. The PingActor is null.
Below is how I am loading my modules in my setup, and registering the Actor Instance.
Static class that contains a helper to help setup my Autofac setup.
public static class IoC
{
public static IContainer Container { get; set; }
public static void Bootstrapping(Action<ContainerBuilder> builderConfig)
{
//new builder instance
var builder = new ContainerBuilder();
builderConfig.Invoke(builder);
Container = builder.Build();
builder = new ContainerBuilder();
builder.ScanAssembly();
builder.Update(Container);
}
}
Here is the ScanAssembly extension method:
public static class ContainerBuilderExtensions
{
public static void ScanAssembly(this ContainerBuilder builder, string searchPattern = "Template.*.dll")
{
var path = AppDomain.CurrentDomain.BaseDirectory;
foreach (var assembly in Directory.GetFiles(path, searchPattern).Select(Assembly.LoadFrom))
{
builder.RegisterAssemblyModules(assembly);
}
}
}
Where I try to register my Actor:
public class IoCModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<ActorSystemShell>().As<IActorSystemShell>();
builder.RegisterType<PingActor>();
}
}
Why am I getting my Actor as Null?
I was missing the AutoFacDependencyResolver.
I modified my code to look as follow:
public void Start()
{
_system = Akka.Actor.ActorSystem.Create(_settings.SystemName);
// Create the dependency resolver
IDependencyResolver resolver = new AutoFacDependencyResolver(IoC.Container, _system);
PingActor = _system.ActorOf(_system.DI().Props<PingActor>(), ActorNames.PingActor);
Console.WriteLine($"Starting actor system: {_settings.SystemName}");
}

An unhandled exception of type 'System.StackOverflowException' occurred in System.Core.dll

In my Asp.net MVC project
I have a bootsrapper that initialize a unity-container.
I don't know why, but I get
An unhandled exception of type 'System.StackOverflowException' occurred in System.Core.dll
I have doubled checked and registration is done only in my initializer.
All dependencies are injected in the ctors only.
What could have caused this?
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
Initializer.Initialize();
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
It fails after BundleConfig.RegisterBundles(BundleTable.Bundles);
public static class Initializer
{
private static bool isInitialize;
private static readonly object LockObj = new object();
private static IUnityContainer defaultContainer = new UnityContainer();
static Initializer()
{
Initialize();
}
public static void Initialize()
{
if (isInitialize)
return;
lock (LockObj)
{
IUnityContainer container = defaultContainer;
//registering Unity for MVC
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
//registering Unity for web API
// GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
#region managers
container.RegisterType<ISettingsManager, SettingsManager>();
container.RegisterType<IMamDataManager, MamDataManager>();
container.RegisterType<IAppsDataManager, AppsDataManager>();
#endregion
#region Dals
container.RegisterType<IDal<ClientService.DAL.EntityFramework.App>, AppsDal>();
#endregion Dals
#region cache
container.RegisterType<ICache<string, ClientService.DAL.EntityFramework.Group>, GroupsCache>(new ContainerControlledLifetimeManager());
container.RegisterType<ICache<string, ClientService.DAL.EntityFramework.App>, AppsCache>(new ContainerControlledLifetimeManager());
container.RegisterType<ICache<string, SettingsServiceData>, SettingsServiceDataCache>(new ContainerControlledLifetimeManager());
#endregion cache
#region Pollers
container.RegisterType<IPoller<ClientService.DAL.EntityFramework.Group>, GroupsPoller>(new ContainerControlledLifetimeManager());
container.RegisterType<IPoller<ClientService.DAL.EntityFramework.App>, AppsPoller>(new ContainerControlledLifetimeManager());
container.RegisterType<IPoller<SettingsServiceData>, SettingsPoller>(new ContainerControlledLifetimeManager());
#endregion Pollers
container.RegisterType<IDefaultConfigurationGroupSingleton, DefaultConfigurationGroupSingleton>(new ContainerControlledLifetimeManager());
container.RegisterType<IApplicationLogger, Log4NetLogger>();
if (!isInitialize)
{
isInitialize = true;
}
}
}
}
Without providing code, I guess this is due to a circular dependency.
Another possible reason is that you have an improper loop in one of your constructors.
As an example, A class requires an instance of B to be resolved; B class requires an instance of C class to be resolved and C class needs an instance of A to be resolved. This results in an infinite loop:
public class A
{
public A(B b)
{
}
}
public class B
{
public B(C c)
{
}
}
public class C
{
public C(A a)
{
}
}
As Rafael mentioned, this is usually caused by circular dependencies, however if you need these dependencies you can fix it by manually resolving some of them.
For example:
// Register the UnityContainer with itself
container.RegisterInstance<IUnityContainer>(container);
public class A
{
public A(B b) {}
}
public class B
{
public B(C c) {}
}
public class C
{
private readonly IUnityContainer _container;
private A _a => _container.Resolve<A>();
public C(IUnityContainer container) {
_container = container;
}
}
This means that C can be constructed without needing to know about A until it's time to use it :)

Categories