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?
source to share
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
.
source to share
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
.
source to share