getting an error when dependency injection in console app with autofac - c#

This question previously asked actually
Using Autofac to inject a dependency into the Main entry point in a console app
Correct use of Autofac in C# console application
Just want to call the non-static method from my main static method in the console app
So I followed the above articles, built in this way
namespace SampleConsoleApp
{
[ExcludeFromCodeCoverage]
public class Program
{
private ISampleService _oSampleService;
private static IContainer CompositionRoot()
{
var builder = new ContainerBuilder();
builder.RegisterType<SampleInitialize>();
builder.RegisterType<SampleService>().As<ISampleService>();
return builder.Build();
}
public static void Main(string[] args)
{
CompositionRoot().Resolve<SampleInitialize>().Run_Auto();
}
}
}
namespace SampleConsoleApp
{
public class SampleInitialize
{
private ISampleService _oSampleService;
public SampleInitialize(ISampleService oSampleService)
{
_oSampleService = oSampleService;
}
public void Run_Auto()
{
var _list = _oSampleService.GetList();
}
}
}
namespace SampleConsoleApp
{
public class SampleService : ISampleService
{
public SampleService(IContext context)
: base(context)
{
_context = context;
}
public List<String> GetList()
{
var _list = new List<String>();
....
return _list;
}
}
}
namespace SampleConsoleApp
{
public interface ISampleService
{
List<String> GetList();
}
}
but I'm getting an error once this launch as following
None of the constructors found with
'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type
'SampleConsoleApp.SampleInitialize' can be invoked with the available
services and parameters:\r\nCannot resolve parameter
'SampleConsoleApp.SampleService.ISampleService oSampleService' of
constructor 'Void .ctor(SampleConsoleApp.ISampleService)'.

As mentioned from #hocho you need to register IContext.
private static IContainer CompositionRoot()
{
var builder = new ContainerBuilder();
builder.RegisterType<SampleInitialize>();
builder.RegisterType<SampleService>().As<ISampleService>();
builder.RegisterType<SampleDbContext>().As<IContext>();
return builder.Build();
}
Afterwards you need to register everything needed by SampleDbContext constructor as well.

Related

Correct way to use Autofac with Factory Pattern?

IN a Winforms project, I have set up Autofac and Factory Pattern and it looks like it's working as expected. However, I'm still not sure whether the following is best practice.
The factory class is:
public static class Client
{
public static readonly IRequestFactory RequestFactory = new RequestFactory();
}
public class Configuration
{
public IContainer Container { get; private set; }
public Configuration()
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.Name.EndsWith("Request"))
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
Container = builder.Build();
}
}
public class RequestFactory : IRequestFactory, IDisposable
{
private ILifetimeScope scope;
public RequestFactory()
{
scope = Client.Configuration.Container.BeginLifetimeScope();
}
public T Get<T>()
{
return scope.Resolve<T>();
}
public void Dispose()
{
if (scope != null)
{
scope.Dispose();
}
}
}
Then, classes in separate assemblies have the IRequestFactory as a ctor parameter.
Is the above the correct way to implement factor pattern with Autofac or is there a better way?

Autofac: Type 'MyController' does not have a default constructor

I have a Web Api app that consumes another REST Api client. I wrapped the REST API client into a service.
myproj/services/PostDataService.cs
public interface IPostDataService
{
Task<IList<Post>> GetAllPosts();
}
public class PostDataService : IPostDataService
{
private static IDataAPI NewDataAPIClient()
{
var client = new DataAPI(new Uri(ConfigurationManager.AppSettings["dataapi.url"]));
return client;
}
public async Task<IList<Post>> GetAllPosts()
{
using (var client = NewDataAPIClient())
{
var result = await client.Post.GetAllWithOperationResponseAsync();
return (IList<Post>) result.Response.Content;
}
}
}
....
I am using AutoFac and injecting the service in the controller
myproj/controllers/PostController.cs
public class PostController : ApiController
{
private readonly IPostDataService _postDataService;
public PostController(IPostDataService postDataService)
{
_postDataService = postDataService;
}
public async Task<IEnumerable<Post>> Get()
{
return await _postDataService.GetAllPosts();
}
}
But I am getting this error.
An error occurred when trying to create a controller of type
'PostController'. Make sure that the controller has a parameterless
public constructor.
Here is my Global.asax.cs
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
ContainerConfig.Configure();
GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
public static class ContainerConfig
{
private static IContainer _container;
public static IContainer GetContainer()
{
if (_container != null)
return _container;
var builder = new ContainerBuilder();
builder.RegisterType<PostDataService>()
.AsSelf()
.InstancePerLifetimeScope()
.AsImplementedInterfaces();
_container = builder.Build();
return _container;
}
public static IContainer Configure()
{
var container = GetContainer();
var webApiResolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = webApiResolver;
return container;
}
Can someone spot what I am missing here?
Thanks
I'm missing
builder.RegisterApiControllers(typeof(PostController).Assembly).
Apparently, the controller also needs to be registered.

How to reuse an InstancePerRequest instance create in composition root using Autofac

I have an Asp.NET MVC5 application in which I registre my types using Autofac in Startup class in this way:
public class Startup
{
public void Configuration(IAppBuilder app)
{
IContainer container = null;
var builder = new ContainerBuilder();
// Register Services
builder.RegisterType<SalesRepository>().As<ISalesRepository>().InstancePerRequest();
builder.RegisterType<SalesService>().As<ISalesService>().InstancePerRequest();
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.AsClosedTypesOf(typeof(IHandle<>))
.AsImplementedInterfaces()
.InstancePerRequest();
builder.Register<IAppEvents>(_ => new AppEvents(container)).InstancePerRequest();
// Register MVC Controllers
builder.RegisterControllers(Assembly.GetExecutingAssembly());
container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
app.UseAutofacMiddleware(container);
app.UseAutofacMvc();
}
}
These are my services (this is a simplified scenario, only for demonstration).
The SalesService class receives a ISalesRepository interface as dependency . In addition I have an AppEvents class where I want to resolve IHandle types:
public interface ISalesRepository { }
public class SalesRepository : ISalesRepository
{
public SalesRepository() { }
}
public interface ISalesService { }
public class SalesService : ISalesService
{
ISalesRepository _repo;
public SalesService(ISalesRepository repo)
{
_repo = repo;
}
}
public interface IHandle<T>
{
void Handle();
}
public class SalesActionHandle : IHandle<string>
{
ISalesRepository _repo;
public SalesActionHandle(ISalesRepository repo)
{
_repo = repo;
}
public void Handle() { }
}
public interface IAppEvents
{
void Raise<T>();
}
public class AppEvents : IAppEvents
{
private readonly IContainer _container;
public AppEvents(IContainer container)
{
if (container == null)
throw new ArgumentNullException("container");
_container = container;
}
public void Raise<T>()
{
var handlers = _container.Resolve<IEnumerable<IHandle<T>>>(); // Runtime error here
foreach (var handler in handlers)
handler.Handle();
}
}
And this is my only (simplified) controller:
public class HomeController : Controller
{
ISalesService _service;
IAppEvents _events;
public HomeController(ISalesService service, IAppEvents events)
{
_service = service;
_events= events;
}
public ActionResult Index()
{
_events.Raise<string>();
return View();
}
}
The problem I have is that I get an error at this line when it is executed:
var handlers = _container.Resolve<IEnumerable<IHandle<T>>>();
No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
I resolve it by doing this:
public void Raise<T>()
{
using (var scope = _container.BeginLifetimeScope("AutofacWebRequest"))
{
var handlers = scope.Resolve<IEnumerable<IHandle<T>>>();
foreach (var handler in handlers)
handler.Handle();
}
}
But in this case, when IHandle is resolved (with SalesActionHandle instance), a new instance of SalesRepository is passed as parameter in SalesActionHandle constructor. What I want is to "reuse" the same instance that SalesService is using (it was created when ISalesService was resolved. I want the same SalesRepository instance for the request)
Is there any way to achieve this behaviour?
The sample code is avaible in Github: https://github.com/josmonver/AutofacTest
You may want to use
AutofacDependencyResolver.Current.RequestLifetimeScope
to match your current request scope, but not to create a new request scope.

SignalR & SimpleInjector silently failing between hub and frontend

I'm trying to set up a signalr hub on my project, using simpleinjector for dependency injection.
I have some configuration in Startup.cs
[assembly: OwinStartup(typeof(Startup))]
namespace CallCentre.Client
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
var container = new Container();
container.Register<TwilioHub>();
container.Verify();
var config = new HubConfiguration()
{
Resolver = new SignalRSimpleInjectorDependencyResolver(container)
};
app.MapSignalR(config);
}
}
}
DI Resolver
public class SignalRSimpleInjectorDependencyResolver : DefaultDependencyResolver
{
private readonly Container _container;
public SignalRSimpleInjectorDependencyResolver(Container container)
{
_container = container;
}
public override object GetService(Type serviceType)
{
return ((IServiceProvider)_container).GetService(serviceType)
?? base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
return _container.GetAllInstances(serviceType)
.Concat(base.GetServices(serviceType));
}
}
My hub
public class TwilioHub : Hub
{
public void Send(int callCount, int queueId)
{
var context = GlobalHost.ConnectionManager.GetHubContext<TwilioHub>();
context.Clients.All.updateQueueCount(callCount, queueId);
}
}
A class elsewhere in the solution where the hub is called
public class QueueStateHandler : IQueueStateHandler
{
private readonly TwilioHub _twilioHub;
public QueueStateHandler(TwilioHub twilioHub)
{
_twilioHub = twilioHub;
}
public void IncrementQueueById(int id)
{
_twilioHub.Send(5,1);
}
}
And my frontend code
$(function () {
var hub = $.connection.twilioHub;
hub.logging = true;
var queue = $('#QueueCount');
hub.client.updateQueueCount = function(queueCount, id) {
alert(queueCount);
};
$.connection.hub.start();
});
I can set everything up using straight web api, skipping the DI and everything works fine. As soon as I bring in DI I start running into problems. At the moment its silently falling over somewhere. I can step through the code and end up in the hub, but nothing happens in my frontend.
Any pointers as to what I'm doing wrong would be greatly appreciated.

Ninject .Net 3.5 SOAP Webservice issues

this is my first time posting up here and trust me I have searched high and low for an answer to my question but have had very little success.
Background: I have currently started trying to re-factor our existing SOAP web service (.Net 3.5) in order to do some IOC and DI using Ninject. I have a CacheManager which I am trying to initalize in the web method, however the injection does not seem to kick in.
I have an console application that calls the webservice with the below:
static void Main(string[] args)
{
TestService service = new CachingService.TestService();
DataResult result = service.GetSomething(1);
}
The webservice is below: TestService.asmx.cs
[WebMethod(Description = "Get something")]
public DataResult GetSomething(int param)
{
try
{
return this.CacheManager.Get();
}
catch (Exception ex)
{
throw;
}
}
Base.cs (TestService.asmx.cs inherits Base to initialize CacheManager)
public class Base
{
[Inject]
public ICacheManager CacheManager
{
get
{
if (cacheProxy == null)
{
cacheProxy = new CacheProxy();
}
return cacheProxy.CacheManager;
}
}
}
CacheProxy.cs
public class CacheProxy
{
[Inject]
public ICacheManager CacheManager { get; set; }
}
CacheManager.cs
public class CacheManager : ICacheManager
{
//implements iCacheManager methods
}
App_Start/NinjectWebCommon.cs
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICacheManager>()
.ToMethod(x => x.Kernel.Get<ICacheManagerFactoryBuilder>().GetCacheManagerFactory().CreateCacheManager())
.InRequestScope();
}
CacheManagerFactoryBuilder.cs
public class CacheManagerFactoryBuilder : ICacheManagerFactoryBuilder
{
private ICacheManagerFactory _Factory;
public CacheManagerFactoryBuilder(ICacheManagerFactory factory)
{
_Factory = factory;
}
public ICacheManagerFactory GetCacheManagerFactory()
{
return _Factory;
}
}
CacheManagerFactory.cs
public class CacheManagerFactory : ICacheManagerFactory
{
private readonly ICacheManager Manager;
public CacheManagerFactory(ICacheManager manager)
{
if (this.Manager == null)
{
this.Manager = manager;
}
}
public ICacheManager CreateCacheManager()
{
return this.Manager;
}
}
Everytime I run the console application and it hits GetSomething, CacheManager is null. Why is it that the injection is not happening when I do a call to the web method?
Another member of the team eventually stumbled across this in another thread here:
How can I implement Ninject or DI on asp.net Web Forms?
All I was missing was inheriting WebServiceBase on my TestService web service class!

Categories

Resources