如何为不同的子类实现多个接口实例?

问题描述 投票:2回答:3

我有一个大类,用于为同一个类的两个不同的集合保存不同的信息。例如,说收据可以是客户收据或内部收据。所有这些信息都在一个巨大的类中,因为这就是数据库的结构,但我想分开这些类,以便我有一个包含所有共享信息的收据类,一个客​​户收据类和一个内部收据类。他们可以共享一个接口,但实现会有所不同,这就是令我困惑的事情。

是否应该实现两个单独的接口?所以我会有一个ICustomerReceipt和IInternalReceipt?我认为应该有一个接口说Get()和Save()方法,并根据实现,如果它是客户或内部收据,我得到特定于该类的信息。我在这里有点失落。

public class Receipt { 
    public int ID { get; set; } 
    public int ReceiptNumber { get; set; }
    public List<string> Items { get; set; }
}

public class CustomerReceipt : Receipt { 
    public string CustomerNumber { get; set; } 
    public string CustomerEmail { get; set; }
    public string CustomerOption { get; set; }
}

public class InternalReceipt : Receipt {
    public string InternalNumber { get; set; }
    public string InternalEmail { get; set; }
    public string InternalOption { get; set; }
}

public interface IReceiptRepository { 
    public Receipt Get(int id);
    public Receipt Add(Receipt receipt);
}

public CustomerReceiptRepository : IReceiptRepository {
    public CustomerReceipt Get(int id) {
        // get information about customer receipts here
    }
}

public InternalReceiptRepository: IReceiptRepository {
    public InternalReceipt Get(int id) {
        // get information about internal receipts here
    }
}

基本上我只想将正确的收据返回到我的控制器中的视图模型,该模型只有通用的“ReceiptNumber”或“ReceiptEmail”。我知道这不是最好的例子,但它是我唯一能想到的。

c# asp.net-core .net-core solid-principles
3个回答
1
投票

不要试图强迫两个类似的东西共享一个抽象(基类或接口)。所以,我建议你建议:创建两个独立的接口。

请记住,多态性的关键在于,如果您只查找基类型/接口的实例,则不必知道实例的具体(派生/实现)类型。而已。如果你不需要那个,那么跳过箍迫使两个相似的类共享一个基础是不值得的。


0
投票
public interface IReceiptRepository { 
    public Receipt Get(int id);
    public Receipt Add(Receipt receipt);
}

public CustomerReceiptRepository : IReceiptRepository {
    public Receipt Get(int id) {
        // get information about customer receipts here
        return new CustomerReceipt();
    }
}

public InternalReceiptRepository: IReceiptRepository {
    public Receipt Get(int id) {
        // get information about internal receipts here
        return new InternalReceipt();
    }
}

0
投票

可以用不同的方式在数据库上表示继承,并且根据您使用的ORM有一些策略。在一天结束时,使用其中一个策略,您可以将存储库基于基类,并让ORM充当代理来解析您需要的实例,或者尝试在存储库级别重新创建,基于鉴别器字段,您需要的实例

Receipt
    ID 
    ReceiptNumber 
    CustomerNumber 
    CustomerEmail 
    CustomerOption 
    InternalNumber 
    InternalEmail 
    InternalOption 
    DISCRIMINATOR_FIELD

(大部分ORM都会为你做这个翻译),但为了让你明白这一点,你可以只保留一个存储库来将所有类视为Receipt并保持你的层次结构。

public interface IReceiptRepository {public Receipt Get(int id);公共收据添加(收据收据); }

public CustomerReceiptRepository : IReceiptRepository {
    public Receipt Get(int id) {
            var rec = DbContext.Table.Receipt.FirstOrDefault(r => r.id = id);
            if(rec.DiscriminatorField == 1) //CustomerReceipt
            {
                return new CustomerReceipt
                {
                     ID = ...
                     ReceiptNumber = ...
                     CustomerNumber = ...
                     CustomerEmail = ...
                     CustomerOption = ...
                 }
              }
              //all other cases are InternalReceipts
              return new InternalReceipt
              {
                   ID = ...
                   ReceiptNumber = ...
                   InternalNumber  = ...
                   InternalEmail = ... 
                   InternalOption = ...
              }
    }
}

Add方法也是如此,只填充该对象所需的字段。这个构成基于鉴别器领域的所有内容。我并不是建议您以这种方式实施您的解决方案,但有了这个,您仍然可以在ViewModel上获得通用收据。我的建议是你阅读更多关于你正在使用的ORM如何在那里表示继承(可能你首先使用数据库而不是代码,你需要手动处理这些东西,因为数据库不是那样设计的并且你需要采用我建议的类似方法。但是如果你有机会创建你的POCO类并创建数据库,那么它肯定值得看看它们如何实现继承。

在这里,我附上了如何在EntityFramework 6上解决此问题的链接

Inheritance Strategy in Entity Framework 6

希望这可以帮助

© www.soinside.com 2019 - 2024. All rights reserved.