0

I have a class in the current assembly called "MyJob"

I want this functionality at runtime:

JobManager.AddJob<MyJob>(s => s.ToRunNow()) //I don't know about "MyJob" at designtime, so I can't do this

If I do this:

var thisAssembly = Assembly.GetExecutingAssembly();
var myJobType = thisAssembly.GetType("MyJob");
JobManager.AddJob<myJobType>(s => s.ToRunNow())

I get this error (at designtime): 'myJobType' is a variable but is used like a type

Btw, this is FluentScheduler but I'm hoping for a generic answer...

  • What is the definition of `AddJob()`? Like what parameters does it accept? – maccettura Jul 18 '18 at 21:01
  • @maccettura: https://github.com/fluentscheduler/FluentScheduler/blob/master/Library/JobFactory.cs – quetzalcoatl Jul 18 '18 at 21:04
  • `JobManager` should have overload of `AddJob` accepting `Type` parameter. – tchelidze Jul 18 '18 at 21:06
  • 2
    @Plutonix: not really. See the code OP attached. He knows `.GetType(string)`. What he does not know is: https://stackoverflow.com/q/10433007/717732 – quetzalcoatl Jul 18 '18 at 21:06
  • @tchelidze: it should, but it does not have it, see the guthub src I provided in other commetn – quetzalcoatl Jul 18 '18 at 21:06
  • Ok, so how do you eventually expect to provide the type if you dont know it? What exactly would be calling this code? – maccettura Jul 18 '18 at 21:08
  • @DavidFromPhila: By the way, even if you do what you described using `MakeGenericMethod`, you will have another problem. The delegate `s => s.ToRunNow()` will probably need to be based on T, so you may need to build the delegate dynamically too. However, if you ensure that MyType is always IMyInterface, and that the IMyInterface has ToRunNow method, then the delegate can be based on IMyInterface and can be compiled normally. If you go this way, then why don;t you check out `public static void AddJob(IJob job, Action schedule)` and the IJob interface. That may save you some work. – quetzalcoatl Jul 18 '18 at 21:10
  • @quetzalcoatl I thought the lambda would be dependent too, but it [turns out its not](https://github.com/fluentscheduler/FluentScheduler/blob/1c3a374d3796c27a93dd53badb0645de9e3fe222/Library/JobManager.cs) – maccettura Jul 18 '18 at 21:11
  • @maccettura: That's simple. Imagine a config file that says: Jobs:Job1, Job2, Job3, JobDaily, JobWeekly, and all of that are tasks' class names that the administrator wants to run. You dont have to recompile the code every time he wants to change it. But you need to read that as strings and then 'convert' it to class name, and then 'convert' it to runnable job or delegate for the Scheduler library. – quetzalcoatl Jul 18 '18 at 21:12
  • @maccettura: I'm getting tired, so sorry, I'll keep it short: OP said `.AddJob(s => s.ToRunNow())`. That's `Action` and IT IS dependent on T. But it can be T=class, or T=interface, the latter being more handy in this case. – quetzalcoatl Jul 18 '18 at 21:13
  • @quetzalcoatl right, but why use the generic overload for that method when you can implement your own factory that returns an instance and use the overload that takes an instance of `IJob`? I was just trying to figure out if this was an XY Problem – maccettura Jul 18 '18 at 21:14
  • I explain how you can dynamically load an add-in here: [C# inherit from a class in a different DLL](https://softwareengineering.stackexchange.com/a/254029/41596) (StackExchange site "Software Engineering"). – Olivier Jacot-Descombes Jul 18 '18 at 21:14
  • @maccettura: `nce and use the overload that takes an instance of IJob` - have you read my comments? thats exactly what I said in the last sentence. – quetzalcoatl Jul 18 '18 at 21:14
  • @quetzalcoatl according to the source code, the only parameter on the generic overload, accepts `Action schedule` as a parameter. Which is _not_ dependent on `T`. See Line:306 [here](https://github.com/fluentscheduler/FluentScheduler/blob/1c3a374d3796c27a93dd53badb0645de9e3fe222/Library/JobManager.cs) – maccettura Jul 18 '18 at 21:15
  • @quetzalcoatl my bad, we are having two discussions on two different things haha. – maccettura Jul 18 '18 at 21:15
  • @OlivierJacot-Descombes: it is worth noting that your link very loosely relates to the problem, and the only thing relevant to be found there is `Activator.CreateInstance`, which may help him in creating the instance of IJob, but that's relevant only provided that OP follows our advise to use `IJob` overload. If he sticks to generics, your comment is totally missed. – quetzalcoatl Jul 18 '18 at 21:17
  • @quetzalcoatl: Generics are often misunderstood as being dynamic. They offer diversity, but are strongly typed and therefore not dynamic. Making things strongly typed by using generics and at the same time using Reflection to create the generic type parameter dynamically is contradictory. Therefore I am suggesting another approach using polymorphism and interfaces. – Olivier Jacot-Descombes Jul 18 '18 at 21:32
  • I'm going to go a different way on this. Instead of having different Jobs (classes implementing IJob), I'm going to have just 1 job class (so it will be known at designtime) and pass in a parameter that defines the job, like this: JobManager.AddJob(new MyJob(3), s => s.ToRunNow()); – DavidFromPhila Jul 19 '18 at 01:03

0 Answers0