My class Is waiting for a Interface but I need initialize a class from a job in the Application_Start.
protected void Application_Start()
{
Bootstrapper.Run();
JobScheduler.RunJobSchedule();
}
On Bootstrap.Run() I have the container builder. like:
private static void SetAutofacContainer()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerRequest();
builder.RegisterType<DbFactory>().As<IDbFactory>().InstancePerRequest();
builder.RegisterAssemblyTypes(typeof(DashboardService).Assembly)
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces().InstancePerRequest();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
And on JobScheduler.RunJobSchedule(); I will initializate my Jobs.
My Job need Instantiate the DashboardHelper class with IDashboardService
public class DashboardHelper
{
public IDashboardService dashboardService { get; }
public DashboardHelper(IDashboardService dashboardService)
{
this.dashboardService = dashboardService;
}
}
My Job Class:
public class ReportWeeklySenderJob : IJob
{
public IDashboardService dashboardService { get; set; }
public async Task Execute(IJobExecutionContext context)
{
this.dashboardService.Mymethods();
}
}
however I can not inject this dependency because the http context has not yet been created.
It should be a stupid question, but I could not solve it.
Related
I'm trying to do some scheduled jobs with Quartz.NET.
When I use constructor in TestJob class for injection, break point not comes here.
When I use property injection in AutofacSettings, it can not set the value of property _userService.
I've tried lots of methods, read so many articles but I'm stuck on this problem.
This solution looks like an answer but due to version updates (I think), it doesn't works for me: How do I create a Quartz.NET’s job requiring injection with autofac
I
AutofacSettings
public class AutofacSettings
{
public static void Run()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerRequest();
builder.RegisterType<DbFactory>().As<IDbFactory>().InstancePerRequest();
builder.RegisterAssemblyTypes(Assembly.Load("DepremsizHayat.Business")).Where(p => p.Name.EndsWith("Service")).AsImplementedInterfaces().InstancePerRequest();
builder.RegisterAssemblyTypes(Assembly.Load("DepremsizHayat.Business")).Where(p => p.Name.EndsWith("Repository")).AsImplementedInterfaces().InstancePerRequest();
RegisterScheduler(builder);
IContainer container = builder.Build();
ConfigureScheduler(container);
AutofacDependencyResolver resolver = new AutofacDependencyResolver(container);
DependencyResolver.SetResolver(resolver);
}
private static void RegisterScheduler(ContainerBuilder builder)
{
var schedulerConfig = new NameValueCollection {
{"quartz.threadPool.threadCount", "3"},
};
builder.RegisterModule(new QuartzAutofacFactoryModule
{
ConfigurationProvider = c => schedulerConfig
});
builder.RegisterModule(new QuartzAutofacJobsModule(typeof(TestJob).Assembly));
builder.RegisterType<TestJobScheduler>().AsSelf();
}
private static void ConfigureScheduler(IContainer container)
{
var scheduler = container.Resolve<TestJobScheduler>();
scheduler.Start();
}
}
TestJob
public class TestJob : IJob
{
public IUserService _userService { get; set; }
Task IJob.Execute(IJobExecutionContext context)
{
System.Diagnostics.Debug.WriteLine(_userService.GetById(1).FIRST_NAME.ToString());
return Task.CompletedTask;
}
}
TestJobScheduler
public class TestJobScheduler
{
private readonly IScheduler _scheduler;
public TestJobScheduler(IScheduler scheduler)
{
this._scheduler = scheduler;
}
public void Start()
{
_scheduler.Start();
IJobDetail job = JobBuilder.Create<TestJob>().Build();
ITrigger trigger = TriggerBuilder.Create().WithSimpleSchedule(
s =>
s
.WithIntervalInSeconds(30).WithRepeatCount(3)
).StartNow().Build();
_scheduler.ScheduleJob(job, trigger);
}
}
Consider Apache Ignite.NET cluster that provides service grid.
There is a simple service, that will run on any node:
public class ClientConnectionService : IClientConnectionService, IService
{
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
[InstanceResource] private IIgnite Ignite { get; set; }
public void Listen(string hostname, int port, uint username, string password,
ClientConnectionListenerOptions options = ClientConnectionListenerOptions.All)
{
Logger.Debug("Listen");
}
public void Init(IServiceContext context)
{
Logger.Debug("Initialized");
}
public void Execute(IServiceContext context)
{
Logger.Debug("Executed");
}
public void Cancel(IServiceContext context)
{
Logger.Debug("Canceled");
}
}
The application is using Castle Windsor as inversion of control container.
I would like to inject custom dependencies, that won't be serialized and transferred over the wire.
Is there any way to achieve it?
N.B. In Java version, there is #SpringResourceannotation that will basically do what I want, but the question is about .NET, that provides just [InstanceResource] attribute.
This is what I have ended up with:
In shared project where all the interfaces and contracts are described I've introduced IContainer
public interface IContainer
{
T Resolve<T>();
}
In project that is responsible for Apache Ignite.NET integration I've implemented simple Apache Ignite.NET plugin
public class DependencyInjectionPlugin
{
public IContainer Container { get; set; }
public T Resolve<T>()
{
return Container.Resolve<T>();
}
}
[PluginProviderType(typeof(DependencyInjectionPluginProvider))]
public class DependencyInjectionPluginConfiguration : IPluginConfiguration
{
public void WriteBinary(IBinaryRawWriter writer)
{
// No-op
}
public int? PluginConfigurationClosureFactoryId { get; } = null; // No Java part
}
public class DependencyInjectionPluginProvider : IPluginProvider<DependencyInjectionPluginConfiguration>
{
public string Name { get; } = "DependencyInjection";
public string Copyright { get; } = "MIT";
protected DependencyInjectionPlugin DependencyInjectionPlugin { get; set; }
public T GetPlugin<T>() where T : class
{
return DependencyInjectionPlugin as T;
}
public void Start(IPluginContext<DependencyInjectionPluginConfiguration> context)
{
DependencyInjectionPlugin = new DependencyInjectionPlugin();
}
public void Stop(bool cancel)
{
}
public void OnIgniteStart()
{
}
public void OnIgniteStop(bool cancel)
{
}
}
In main project, that is responsible for wiring up all components, I've implemented IContainer, defined previously, and registered it in Castle Windsor:
public class DependencyInjectionContainer : IContainer
{
protected IKernel Kernel { get; set; }
public DependencyInjectionContainer(IKernel kernel)
{
Kernel = kernel;
}
public T Resolve<T>()
{
return Kernel.Resolve<T>();
}
}
public class DependencyInjectionInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component
.For<IContainer>()
.ImplementedBy<DependencyInjectionContainer>()
);
}
}
In the very same project I've registered Apache Ignite.NET
public class IgniteInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component
.For<IIgnite>()
.UsingFactoryMethod(() => Ignition.Start(new IgniteConfiguration
{
PluginConfigurations = new[] {new DependencyInjectionPluginConfiguration()}
}))
);
}
}
Finally, in application's main method:
// Build Windsor container
using (var container = new WindsorContainer())
{
// Install DI abstraction layer
container.Install(new DependencyInjectionInstaller());
// Install cluster abstraction layer
container.Install(new IgniteInstaller());
// Attach DI container to cluster plugin
container
.Resolve<IIgnite>()
.GetPlugin<DependencyInjectionPlugin>("DependencyInjection")
.Container = container.Resolve<IContainer>();
// Wait
Done.Wait();
}
That's it. From now on, I am able to access IContainer implementation in Apache Ignite.NET distributed service like this:
var plugin = Ignite.GetPlugin<DependencyInjectionPlugin>("DependencyInjection");
var whatever = plugin.Resolve<IWhatever>();
I have an application that is written with c# on the top of the ASP.NET MVC 5 Framework. I implemented Unity.Mvc into my project. Now, I am trying to inject dependencies objects into my SignalR Hub.
I created a class called UnityHubActivator
My class looks like this
public class UnityHubActivator : IHubActivator
{
private readonly IUnityContainer _container;
public UnityHubActivator(IUnityContainer container)
{
_container = container;
}
public IHub Create(HubDescriptor descriptor)
{
return (IHub)_container.Resolve(descriptor.HubType);
}
}
Then in my UnityConfig class I added the following to my RegisterTypes method
var unityHubActivator = new UnityHubActivator(container);
container.RegisterInstance<IHubActivator>(unityHubActivator);
My hub looks like this
[Authorize]
public class ChatHub : Hub
{
protected IUnitOfWork UnitOfWork { get; set; }
public ChatHub(IUnitOfWork unitOfWork)
: base()
{
UnitOfWork = unitOfWork;
}
}
But when I run the hub, the constructor never get called and the connection never takes place.
How can I correctly use Unity framework to inject dependencies into my hub?
UPDATED
I tried to created a custom container like so
public class UnitySignalRDependencyResolver: DefaultDependencyResolver
{
protected IUnityContainer Container;
private bool IsDisposed = false;
public UnitySignalRDependencyResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
Container = container.CreateChildContainer();
}
public override object GetService(Type serviceType)
{
if (Container.IsRegistered(serviceType))
{
return Container.Resolve(serviceType);
}
return base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
if (Container.IsRegistered(serviceType))
{
return Container.ResolveAll(serviceType);
}
return base.GetServices(serviceType);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if(IsDisposed)
{
return;
}
if(disposing)
{
Container.Dispose();
}
IsDisposed = true;
}
}
Then here is how I configured the hub in the Startup class
public class Startup
{
public IUnityContainer Container { get; set; }
public Startup(IUnityContainer container)
{
Container = container;
}
public void Configuration(IAppBuilder app)
{
app.Map("/signalr", map =>
{
var resolver = new UnitySignalRDependencyResolver(Container);
var hubConfiguration = new HubConfiguration
{
Resolver = resolver
};
map.RunSignalR(hubConfiguration);
});
}
}
But still now working... the hub constructor never get called.
Here is how I am calling my hub from the client
<script src="~/Scripts/jquery.signalR-2.2.2.min.js"></script>
<script src="~/signalr/hubs"></script>
<script>
$(function () {
// Reference the auto-generated proxy for the hub.
var app = $.connection.chatHub;
console.log('Getting things ready....');
app.client.outOfTasks = function () {
console.log('Nothing to do here')
};
app.client.logError = function (message) {
console.log(message)
};
app.client.logNote = function (message) {
console.log(message)
};
app.client.assignTask = function (taskId) {
app.server.taskReceived();
console.log('task received!!!' + taskId);
};
// Start the connection.
$.connection.hub.start().done(function () {
console.log('Connection Started....');
});
});
</script>
The UnitySignalRDependencyResolver appears accurate for that container.
Taken from the official documentation,
Dependency Injection in SignalR
try the following example for configuring Startup
public class Startup{
public void Configuration(IAppBuilder app) {
IUnityContainer container = GetContainer();
var resolver = new UnitySignalRDependencyResolver(container);
var config = new HubConfiguration {
Resolver = resolver
};
app.MapSignalR("/signalr", config);
}
IUnityContainer GetContainer() {
//...call the unity config related code.
var container = UnityConfig.Container;
//...any other code to populate container.
return container;
}
}
Make sure to register the necessary objects, including the hub (ChatHub) with the container as the container needs to know the object graph in order to resolve the necessary dependencies.
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>>();
}
I want to inject my DbContext into all controllers.
public abstract class MyController: Controller
{
public MyDbContext db { get; set; }
}
protected void Application_Start()
{
[..]
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
builder.RegisterType<MyDbContext>().InstancePerHttpRequest();
}
However, when I access base.db in any controller, it is null.
What am I missing here?