扩展接口实现?
Extend Interface Implementation?
我有一个小型对象工厂,可以创建两种类型的对象。现在我想向第二个对象添加新方法但不更改接口,因为我也必须在第一个对象中实现该方法。怎么做?
public class LookupFactory
{
public ILookups CreateLookups()
{
ILookups dbLookup = null;
var databaseType = ConfigurationManager.AppSettings["databaseType"].ToString();
switch (databaseType.ToLower())
{
case "oracle":
dbLookup = new Lookups();
break;
case "mssql":
dbLookup = new SqlLookups();
break;
}
return dbLookup;
}
}
我的界面是这样的:
public interface ILookups
{
List<Region> GetRegions(string language);
List<Industry> GetIndustries(string language);
List<Dimension> GetDimensions(string language);
List<SubjectType> GetSubjectTypes(string language);
}
我只想将方法 GetPeople 添加到 SqlLookups 对象。
嗯,如果两个 classes 实现一个接口,它们必须实现所有方法。所以,如果你想在你的接口中添加新方法,你必须在 Lookups
和 SqlLookups
中实现它。
可能的解决方案:
创建新界面IExtendedLookups : ILookups
并添加新界面
IExtendedLookups
并使 class SqlLookups : IExtendedLookups
的方法
您的工厂应该 return ILookups 但稍后在代码中您必须检查 returned 值:
var lookups = factory.CreateLookups();
var extendedLookups = lookups as IExtendedLookups;
if (extendedLookups != null)
{
//...call extendedLookups.GetPeople();
}
向 ILookups 添加新方法,在两个 classes 中实现,但在 Lookups 中这样做:
public List<People> GetPeople()
{
throw new NotSupportedException();
}
你必须问自己这个问题 "consumer side"。
作为起点,我会这样做:
生成仅由特定 classes 实现的精致接口:
public interface ILookups
{
List<Region> GetRegions(string language);
List<Industry> GetIndustries(string language);
List<Dimension> GetDimensions(string language);
List<SubjectType> GetSubjectTypes(string language);
// maybe add this
// this makes it clear to the consumer that it could receive an extended lookup
// one class returns "this", the other "null"
IExtendedLookUps GetExtendedOrNull { get;}
}
public interface IExtendedLookups : ILookups
{
List<People> GetPeople();
}
void consumerCode()
{
ILookups lookups = factory.CreateLookups();
// code that works for both cases
lookups.GetRegions("en");
// do something special if it implements IExtendedLookups
if (lookups is IExtendedLookups)
{
var extendedLookups = lookups as IExtendedLookups;
extendedLookups.GetPeople();
}
// or with the additional interface property:
var maybeExtendedLookups = lookups.GetExtendedOrNull;
if (maybeExtendedLookups != null)
{
maybeExtendedLookups.GetPeople();
}
}
如果额外的方法只与单一目的相关(例如生成某个报告),那么可以在界面中包含此报告生成。
如果有合适的 "default" 值(如您的情况下的空列表),请将其添加到另一个 class。如果没有合适的默认就不要做。
总结一下:这完全取决于你想如何使用它。从使用到实现的设计而不是相反!
我有一个小型对象工厂,可以创建两种类型的对象。现在我想向第二个对象添加新方法但不更改接口,因为我也必须在第一个对象中实现该方法。怎么做?
public class LookupFactory
{
public ILookups CreateLookups()
{
ILookups dbLookup = null;
var databaseType = ConfigurationManager.AppSettings["databaseType"].ToString();
switch (databaseType.ToLower())
{
case "oracle":
dbLookup = new Lookups();
break;
case "mssql":
dbLookup = new SqlLookups();
break;
}
return dbLookup;
}
}
我的界面是这样的:
public interface ILookups
{
List<Region> GetRegions(string language);
List<Industry> GetIndustries(string language);
List<Dimension> GetDimensions(string language);
List<SubjectType> GetSubjectTypes(string language);
}
我只想将方法 GetPeople 添加到 SqlLookups 对象。
嗯,如果两个 classes 实现一个接口,它们必须实现所有方法。所以,如果你想在你的接口中添加新方法,你必须在 Lookups
和 SqlLookups
中实现它。
可能的解决方案:
创建新界面
IExtendedLookups : ILookups
并添加新界面IExtendedLookups
并使 classSqlLookups : IExtendedLookups
的方法 您的工厂应该 return ILookups 但稍后在代码中您必须检查 returned 值:var lookups = factory.CreateLookups(); var extendedLookups = lookups as IExtendedLookups; if (extendedLookups != null) { //...call extendedLookups.GetPeople(); }
向 ILookups 添加新方法,在两个 classes 中实现,但在 Lookups 中这样做:
public List<People> GetPeople() { throw new NotSupportedException(); }
你必须问自己这个问题 "consumer side"。
作为起点,我会这样做:
生成仅由特定 classes 实现的精致接口:
public interface ILookups { List<Region> GetRegions(string language); List<Industry> GetIndustries(string language); List<Dimension> GetDimensions(string language); List<SubjectType> GetSubjectTypes(string language); // maybe add this // this makes it clear to the consumer that it could receive an extended lookup // one class returns "this", the other "null" IExtendedLookUps GetExtendedOrNull { get;} } public interface IExtendedLookups : ILookups { List<People> GetPeople(); } void consumerCode() { ILookups lookups = factory.CreateLookups(); // code that works for both cases lookups.GetRegions("en"); // do something special if it implements IExtendedLookups if (lookups is IExtendedLookups) { var extendedLookups = lookups as IExtendedLookups; extendedLookups.GetPeople(); } // or with the additional interface property: var maybeExtendedLookups = lookups.GetExtendedOrNull; if (maybeExtendedLookups != null) { maybeExtendedLookups.GetPeople(); } }
如果额外的方法只与单一目的相关(例如生成某个报告),那么可以在界面中包含此报告生成。
如果有合适的 "default" 值(如您的情况下的空列表),请将其添加到另一个 class。如果没有合适的默认就不要做。
总结一下:这完全取决于你想如何使用它。从使用到实现的设计而不是相反!