我知道有类似的问题,但我没有发现任何与我所做的相似的事情。
假设我有这个:
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
需要一个不被界面强制执行的setter。
我最初使用的是双IJob
界面(IJob
和IJob<T>
)但这意味着我必须从IJob<T>
投射到IJob
并且我没有'那样的。
有没有更清洁的方法呢?
答案 0 :(得分:2)
更新
我最初的建议是创建一个抽象类,在构造函数中设置Data,
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
方法。
答案 1 :(得分:1)
据我所知,您希望在继承上强制执行setter定义,这也将具有可访问性限制!如果您定义了一个setter方法,您仍然可以将其公开访问。并且,“双IJob
界面(IJob
和IJob<T>
)但这意味着我必须从IJob<T>
投射到IJob
”听起来不太好给你。
对于这种情况没有太多解决方案,但可以使用抽象类来解决一个问题。我在这里建议的是这样的:
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
}
}
现在,您没有对后续类实现IJob
,而是扩展Abs_JobA
抽象类。