C# 扩展接口实现?

C# 扩展接口实现?,c#,interface,factory-pattern,C#,Interface,Factory Pattern,我有一个小对象工厂,它创建两种类型的对象。现在我想向第二个对象添加新方法,但不更改接口,因为我必须在第一个对象中实现该方法。怎么做 public class LookupFactory { public ILookups CreateLookups() { ILookups dbLookup = null; var databaseType = ConfigurationManager.AppSettings["databaseType"].ToS

我有一个小对象工厂,它创建两种类型的对象。现在我想向第二个对象添加新方法,但不更改接口,因为我必须在第一个对象中实现该方法。怎么做

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);
 }
public List<People> GetPeople()
{
    throw new NotSupportedException();
}
公共接口ILookups
{
列表区域(字符串语言);
列表(字符串语言);
列表GetDimensions(字符串语言);
列出GetSubjectTypes(字符串语言);
}

我只想将方法GetPeople添加到SqlLookups对象。

如果两个类实现一个接口,那么它们必须实现所有方法。因此,如果要向接口添加新方法,必须在
Lookups
SqlLookups
中实现它。 可能的解决办法:

  • 创建新接口
    IExtendedLookups:ILookups
    并添加新接口 方法来
    IExtendedLookups
    并生成类
    sqllookup:IExtendedLookups
    您的工厂应该返回ILookups,但稍后在代码中您必须检查返回的值:

    var lookups = factory.CreateLookups();
    var extendedLookups = lookups as IExtendedLookups;
    if (extendedLookups != null)
    {
        //...call extendedLookups.GetPeople();
    }
    
  • 将新方法添加到ILookups,在两个类中实现,但在查找中执行如下操作:

    public interface ILookups
    {
        List<Region> GetRegions(string language);
    
        List<Industry> GetIndustries(string language);
    
        List<Dimension> GetDimensions(string language);
    
        List<SubjectType> GetSubjectTypes(string language);
     }
    
    public List<People> GetPeople()
    {
        throw new NotSupportedException();
    }
    
    public List GetPeople()
    {
    抛出新的NotSupportedException();
    }
    

  • 如果两个类实现一个接口,那么它们必须实现所有方法。因此,如果要向接口添加新方法,必须在
    Lookups
    SqlLookups
    中实现它。 可能的解决办法:

  • 创建新接口
    IExtendedLookups:ILookups
    并添加新接口 方法来
    IExtendedLookups
    并生成类
    sqllookup:IExtendedLookups
    您的工厂应该返回ILookups,但稍后在代码中您必须检查返回的值:

    var lookups = factory.CreateLookups();
    var extendedLookups = lookups as IExtendedLookups;
    if (extendedLookups != null)
    {
        //...call extendedLookups.GetPeople();
    }
    
  • 将新方法添加到ILookups,在两个类中实现,但在查找中执行如下操作:

    public interface ILookups
    {
        List<Region> GetRegions(string language);
    
        List<Industry> GetIndustries(string language);
    
        List<Dimension> GetDimensions(string language);
    
        List<SubjectType> GetSubjectTypes(string language);
     }
    
    public List<People> GetPeople()
    {
        throw new NotSupportedException();
    }
    
    public List GetPeople()
    {
    抛出新的NotSupportedException();
    }
    

  • 你必须问自己,从“消费者方面”看,它应该如何运作

    作为起点,我会这样做:

  • 生成仅由特定类实现的优化接口:

    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();
        }
    
     }
    
    公共接口ILookups
    {
    列表区域(字符串语言);
    列表(字符串语言);
    列表GetDimensions(字符串语言);
    列出GetSubjectTypes(字符串语言);
    //也许再加上这个
    //这向消费者表明,它可以接收扩展的查找
    //一个类返回“this”,另一个类返回“null”
    IExtendedLookUps GetExtendedOrNull{get;}
    }
    公共接口IExtendedLookups:ILookups
    {
    列出GetPeople();
    }
    void consumerCode()
    {
    ILookups lookups=factory.CreateLookups();
    //适用于这两种情况的代码
    查找。获取区域(“en”);
    //如果它实现了IExtendedLookups,请执行一些特殊的操作
    if(查找为IExtendedLookups)
    {
    var extendedLookups=作为IExtendedLookups的查找;
    extendedLookups.GetPeople();
    }
    //或使用附加的接口属性:
    var maybeExtendedLookups=lookups.GetExtendedOrNull;
    if(maybeExtendedLookups!=null)
    {
    maybeextendlookups.GetPeople();
    }
    }
    
  • 如果额外方法仅与单一目的相关(例如生成特定报告),则可能在界面中包含此报告生成

  • 如果有一个合适的“default”值(如您的示例中的空列表),请将其添加到另一个类中。如果没有合适的默认值,就不要这样做


  • 总而言之:这完全取决于你想如何使用它。从使用到实现的设计,而不是相反

    你必须问自己,从“消费者方面”看,它应该如何运作

    作为起点,我会这样做:

  • 生成仅由特定类实现的优化接口:

    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();
        }
    
     }
    
    公共接口ILookups
    {
    列表区域(字符串语言);
    列表(字符串语言);
    列表GetDimensions(字符串语言);
    列出GetSubjectTypes(字符串语言);
    //也许再加上这个
    //这向消费者表明,它可以接收扩展的查找
    //一个类返回“this”,另一个类返回“null”
    IExtendedLookUps GetExtendedOrNull{get;}
    }
    公共接口IExtendedLookups:ILookups
    {
    列出GetPeople();
    }
    void consumerCode()
    {
    ILookups lookups=factory.CreateLookups();
    //适用于这两种情况的代码
    查找。获取区域(“en”);
    //如果它实现了IExtendedLookups,请执行一些特殊的操作
    if(查找为IExtendedLookups)
    {
    var extendedLookups=作为IExtendedLookups的查找;
    extendedLookups.GetPeople();
    }
    //或使用附加的接口属性:
    var maybeExtendedLookups=lookups.GetExtendedOrNull;
    if(maybeExtendedLookups!=null)
    {
    maybeextendlookups.GetPeople();
    }
    }
    
  • 如果额外方法仅与单一目的相关(例如生成特定报告),则可能在界面中包含此报告生成

  • 如果有一个合适的“default”值(如您的示例中的空列表),请将其添加到另一个类中。如果没有合适的默认值,就不要这样做


  • 总而言之:这完全取决于你想如何使用它。从使用到实现的设计,而不是相反

    显然,有一些原因不能简单地“向第二个对象添加新方法”——您介意澄清一下它是什么吗?(可能与您计划如何使用对象有关)您可以添加该方法,但不能从
    ILookups
    引用调用它。您必须测试返回的实例是否是
    SqlLookups
    (或者更确切地说是
    IGetPeople
    ),将其转换为该实例,然后调用该方法。显然,您不能简单地“将新方法添加到第二个对象”是有原因的,您介意澄清一下它是什么吗?(可能与您计划如何使用这些对象有关)您可以向我添加