这是课堂设计问题。
我有主要的抽象类
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions {get;};
}
public interface IRestriction{}
public interface IRestriction<T>:IRestriction where T:struct
{
T Limit {get;}
}
public TimeRestriction:IRestriction<TimeSpan>
{
public TimeSpan Limit{get;set;}
}
public AgeRestriction:IRestriction<int>
{
public int Limit{get;set;}
}
public class BlockRule:AbstractBlockRule
{
public virtual List<IRestriction> Restrictions {get;set;}
}
BlockRule rule=new BlockRule();
TimeRestriction t=new TimeRestriction();
AgeRestriction a=new AgeRestriction();
rule.Restrictions.Add(t);
rule.Restrictions.Add(a);
我必须使用非通用接口IR限制,以避免在主抽象类中指定泛型类型T.我对仿制药很新。有人可以让我知道如何更好地设计这个东西吗?
答案 0 :(得分:21)
您的方法很典型(例如,IEnumerable&lt; T&gt;像这样实现IEnumerable)。如果要为代码的使用者提供最大效用,那么在非泛型接口上提供非泛型访问器,然后将其隐藏在通用实现中会很不错。例如:
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions { get; set; }
}
public interface IRestriction
{
object Limit { get; }
}
public interface IRestriction<T> : IRestriction
where T:struct
{
// hide IRestriction.Limit
new T Limit {get;}
}
public abstract class RestrictionBase<T> : IRestriction<T>
where T:struct
{
// explicit implementation
object IRestriction.Limit
{
get { return Limit; }
}
// override when required
public virtual T Limit { get; set; }
}
public class TimeRestriction : RestrictionBase<TimeSpan>
{
}
public class AgeRestriction : RestrictionBase<TimeSpan>
{
}
public class BlockRule : AbstractBlockRule
{
public override List<IRestriction> Restrictions { get; set; }
}
我还在这里展示了使用基本限制类,但这不是必需的。
答案 1 :(得分:5)
运行时将IRestriction<TimeSpan>
和IRestriction<int>
视为不同的不同类(它们甚至有自己的一组静态变量)。在您的情况下,继承层次结构中IRestriction<TimeSpan>
和IRestriction<int>
共有的唯一类是IRestriction
和object
。
事实上,拥有IRestriction
列表是唯一明智的选择。
请注意:无论您是在处理Limit
还是IRestriction<TimeSpan>
,您都可以在其中找到属性IRestriction<int>
。在这种情况下,我要做的是在object Limit { get; }
上定义另一个属性IRestriction
,并将其隐藏在实际实现中。像这样:
public interface IRestriction
{
object Limit { get; }
}
public interface IRestriction<T> : IRestriction
where T : struct
{
new T Limit { get; set; }
}
public class TimeRestriction : IRestriction<TimeSpan>
{
public TimeSpan Limit { get; set; }
// Explicit interface member:
// This is hidden from IntelliSense
// unless you cast to IRestriction.
object IRestriction.Limit
{
get
{
// Note: boxing happens here.
return (object)Limit;
}
}
}
这样,当您不关心它的类型时,您可以在所有Limit
上object
IRestriction
访问foreach(IRestriction restriction in this.Restrictions)
{
Console.WriteLine(restriction.Limit);
}
。例如:
{{1}}
答案 2 :(得分:0)
接口是实现合同的实体需要遵循的合同。
您已创建两个名称为IRestriction
据我所知,你基本上可能需要的是一个可以限制的类的标志,它应该实现IRestriction
非通用接口。
第二个接口似乎是也包含limit属性的可限制对象。
因此,第二个IRestriction
接口的定义可以是ILimitRestriction
或任何适合您业务需求的名称。
因此ILimitRestriction
可以继承自IRestriction
,这会标记继承ILimitRestriction
IRestriction
个对象的类
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions {get;};
}
public interface IRestriction{}
public interface IRestrictionWithLimit<T>:IRestriction where T:struct
{
T Limit {get;}
}
public TimeRestriction:IRestrictionWithLimit<TimeSpan>
{
public TimeSpan Limit{get;set;}
}
public AgeRestriction:IRestrictionWithLimit<int>
{
public int Limit{get;set;}
}
public class BlockRule:AbstractBlockRule
{
public virtual List<IRestriction> Restrictions {get;set;}
}