我知道有人问过类似的问题,但没有找到与我所做的足够相似的问题。
假设我有这个:
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
界面(IJob
和IJob<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/