-1

Im sure this must be possibly, but it is beyond me at present.

I have a method that initialises several jobs, based around quartz engine. for example

private void InitialiseJobs(IScheduler scheduler)
{
    var ns = "Proto.QuartzScheduler.Domain.Jobs";
    var classname = "ExampleJob";

    var jobSetup = new JobSetup<type>(scheduler);
    jobSetup.Run(10);

    var second_jobSetup = new JobSetup<ExampleJob>(scheduler);
    second_jobSetup.Run(20);
}

The last two lines of this work. I want to be able to define the type via the namespace and class name and pass in into the generic type. e.g replace ExampleJob with whatever I define.

Any help appreciated.

Apologies I should have given you all a bit more than prevent the suggestion below from working:

public class JobSetup<TType> where TType : IJobToDo
{

    private readonly IScheduler scheduler;
    private readonly IJobDetail jobDetail;
    private readonly JobKey jobKey;

    public JobSetup(IScheduler scheduler)
    {
        this.scheduler = scheduler;
        this.jobKey = new JobKey(Guid.NewGuid().ToString(), typeof(TType).ToString());
        this.jobDetail = JobBuilder
                            .Create<JobRunner<TType>>()
                            .WithIdentity(this.jobKey)
                            .Build();
    }

    public void Set<TPropertyType>(Expression<Func<TType, TPropertyType>> expression, TPropertyType value)
    {

        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression == null)
        {
            throw new ArgumentException("Could not convert the expression to a member expression.");
        }

        this.jobDetail.JobDataMap[memberExpression.Member.Name] = value;
    }

    public TPropertyType Get<TPropertyType>(Expression<Func<TType, TPropertyType>> expression)
    {
        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression == null)
        {
            throw new ArgumentException("Could not convert the expression to a member expression.");
        }

        return (TPropertyType)this.jobDetail.JobDataMap.Get(memberExpression.Member.Name);
    }

    public void Run(int number_of_seconds)
    {

        var trigger = new SimpleTriggerImpl
        (
            this.jobKey.Name,
            this.jobKey.Group,
            DateTime.UtcNow,
            null,
            SimpleTriggerImpl.RepeatIndefinitely,
            TimeSpan.FromSeconds(number_of_seconds)
        );

        this.scheduler.ScheduleJob(this.jobDetail, trigger);
    }
}

And the interface:

public interface IJobToDo
{
    void Run();
}

And the ExampleJob

public class ExampleJob : IJobToDo
{

    public void Run()
    {
        Console.WriteLine("HelloJob is executing. {0}", System.DateTime.Now.ToUniversalTime());

    }
}

I dont have a parameterless constructor for the class being activated?

Keep the suggestions comming please

Cheers

  • 2
    duplicate of [Pass An Instantiated System.Type as a Type Parameter for a Generic Class](http://stackoverflow.com/questions/266115/pass-an-instantiated-system-type-as-a-type-parameter-for-a-generic-class) – BartoszKP Jul 01 '14 at 08:25
  • Please explain what error you're getting. And why the question linked above isn't enough. – BartoszKP Jul 01 '14 at 11:38
  • I dont have a parameterless constructor for the class being activated? – Justdeserves Jul 01 '14 at 12:12
  • I don't know, do you? – BartoszKP Jul 01 '14 at 12:19
  • No i dont know! - Implementing the above I dont get the opportunity to call second_jobSetup.Run(20); just second_jobSetup.Run(); The first being in JobSetup class and the second in the ExampleJob class. I need the first. – Justdeserves Jul 01 '14 at 13:34
  • I don't know the class you're using, but I assume you know it. So you should be able to determine easily whether it has a parameterless constructor or not. Therefore I completely don't understand your question. Why would you ask that? Just check whether this constructor exists or not. I assume though that in reality you want to ask a different question, but it's hard to guess what is it. – BartoszKP Jul 01 '14 at 14:04
  • OK - so I solved this one myself. It was faily simple in that JobSetup needed an interface defining. I then used Ninject to create and binding between the interface and the class of the correct type e.g kernel.Bind().To>(); It was then possible to resolve the dependacy in initialiseJobs method – Justdeserves Jul 02 '14 at 14:20
  • Please consider either editing your question and self-answering it **if it could be helpful to other people in the future**. Otherwise you can delete it. – BartoszKP Jul 02 '14 at 15:48

1 Answers1

0

If your JobSetup<> generic class implements some interface like:

interface IJobSetup
{
    void Run(int x);
}

you can use object created by Activator via interface, which is more elegant. So write it as:

private void InitialiseJobs(IScheduler scheduler)
{
    var classname = "Proto.QuartzScheduler.Domain.Jobs.ExampleJob";
    Type genericTypeParameter = Type.GetType(classname);
    Type genericClass = typeof(JobSetup<>);
    Type constructedClass = genericClass.MakeGenericType(genericTypeParameter);

    var setup = Activator.CreateInstance(constructedClass) as IJobSetup;
    setup.Run(20);
}
Konrad Kokosa
  • 16,563
  • 2
  • 36
  • 58
  • Hm.. Why downvoted? I've answered with case-specific scenario, adding information about interface (to point how object created by `Activator` can be consumed). – Konrad Kokosa Jul 01 '14 at 08:49