我知道有人问过类似的问题,但没有找到与我所做的足够相似的问题。

假设我有这个:

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's get plus a set

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

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


而且,由于使用了out参数,这也可以工作:

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();
}


尽管这很好用,但感觉就像是在破解,因为我必须记住JobA需要一个不受接口强制的设置器。
我最初使用的是双重IJob界面(IJobIJob<T>),但这意味着我必须从IJob<T>转换为IJob,但我不喜欢这样。
有没有更清洁的方法可以做到这一点?

最佳答案

更新

我最初的建议是创建一个抽象类,以在构造函数中设置数据,

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();
}


强制派生类设置JobData属性。

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

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


原始答案

遵循抽象基类的想法,考虑一个抽象工厂方法,该方法将强制任何派生类在属性本身中提供数据

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

    public abstract void Run();

    public abstract T GetData();
}


或拥有一个私有的setter并在构造函数中设置一次

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();
}


任何派生的实现都将被强制实现GetData方法。

关于c# - 具有通用接口(interface)参数的通用接口(interface)列表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44780070/

10-10 09:30