Common interface list with common interface parameter

I know similar questions have been asked, but I haven't found any that are similar enough to what I have done.

Let's say I have this:

public interface IData
{
    string Data { get; set; }
}
public interface IJob<out T> where T: IData
{
    T JobData { get; } // works because no setter

    void Run();
}

public class JobAData : IData
{
    public string Data { get; set; }
}

public class JobA : IJob<JobAData>
{
    public JobAData JobData { get; private set; } // implements IJob get plus a set

    public JobA(JobAData data)
    {
        JobData = data;
    }

    public void Run()
    {
        //can use JobData nicely here
    }
}

      

And, because of the out parameter, this also works:

List<IJob<IData>> jobs = new List<IJob<IData>>();
jobs.Add(new JobA(new JobAData()));

//in another class, extremely simplified (actually running with Quartz)
foreach (var job in jobs)
{
    job.Run();
}

      

While this works fine, this seems like a hack as I have to remember that I JobA

need a setter that is not enforced by the interface.
Initially, I used the dual interface IJob

( IJob

and IJob<T>

), but it meant that I had to throw away from IJob<T>

before IJob

, and I did not like it.
Is there a cleaner way to do this?

+3


source to share


2 answers


UPDATE

My initial suggestion was to create an abstract class that sets the data in the constructor,

public abstract class JobBase<T> : IJob<T> where T : IData {

    public JobBase(T data) {
        JobData = data;
    }

    public T JobData { get; private set; }

    public abstract void Run();
}

      

forcing derived classes to set a property JobData

.

public class JobA : JobBase<JobAData> {
    public JobA(JobAData data) : base(data) { }

    public void Run() {
        //can use JobData nicely here
    }
}

      

ORIGINAL ANSWER



Following the idea of ​​an abstract base class, consider an abstract factory method that will cause any derived class to provide data either in the property itself

public abstract class JobBase<T> : IJob<T> where T : IData {
    public T JobData { get { return GetData(); } }

    public abstract void Run();

    public abstract T GetData();
}

      

or having a private setter and setting it once in the constructor

public abstract class JobBase<T> : IJob<T> where T : IData {

    public JobBase() {
        JobData = GetData();
    }

    public T JobData { get; private set; }

    public abstract void Run();

    public abstract T GetData();
}

      

Any derived implementations will be forced to implement the method GetData

.

+1


source


From what I understand, you want to set a setter definition in inheritance, which will also have an accessibility constraint! If you define a setter method, you still make it public. And "dual interface IJob

( IJob

and IJob<T>

), but it meant that I had to drop off IJob<T>

to IJob

," it's not good for you.

There are not many solutions to this situation, but one work might be limited to using abstract classes. I suggest something like this here:



public interface IData
{
    string Data { get; set; }
}
public interface IJob<out T> where T : IData
{
    T JobData { get; }

    void Run();
}

public class JobAData : IData
{
    public string Data { get; set; }
}

public abstract class Abs_JobA : IJob<JobAData>
{
    public abstract JobAData JobData { get; protected set; }
    public abstract void Run();
}

public class JobA : Abs_JobA
{
    public override JobAData JobData
    {
        get;
        protected set;
    }

    public JobA(JobAData data)
    {
        this.JobData = data;
    }

    public override void Run()
    {
        //can use JobData nicely here
    }
}

      

So now you are not implementing IJob

for subsequent classes, but rather extending the abstract class Abs_JobA

.

+1


source







All Articles