具有显式类型转换的 C# 接口继承

C# interface inheritance with explicit typecast

我有一项服务可以创建、保存和发送不同类型的订单,其中某些类型的订单可以携带附件。 该服务将使用 IExternalService 将订单发送到另一个外部服务,该服务由具有不同外部端点的其他几个服务使用。

IExternalService 包含用于向外部服务发送订单的外部 IRepository 的 getter。

我已经为那些将添加附件 IRepositoryWithAttachement 的存储库创建了一个新接口。

我在下面提供了一些示例代码,其中我遗漏了不重要的内容:

interface IRepository //Standard repo used by different external services
{
string Create(Order order);
void Update(Order order);
}

带附件的订单使用

interface IRepositoryWithAttachement : IRepository //attachable repo
{
string AddFile(Attachement file);
void UpdateFile(Attachement file);
}

必须发送附件和订单的回购

public class Repository : IRepositoryWithAttachement {...} 

许多外部服务的实现使用的服务

interface IExternalService 
{
 string Name { get; }
 ....
IRepository Repository { get; }
}

用于创建、保存和发送订单的主要服务class

public class OrderService
{
public string Create(Order order)
{
...
IExternalService eService = _externalServices.GetExternalService(id);

try
        {                
         eService.Repository.Create(order);
        }
        catch (Exception e)
        {
            ....
        }
 ...
} 

现在这个特定的订单类型将添加附件,当它使用 IExternalService 获取存储库时,它将返回一个 IRepository 并尝试调用 eService.Repository.AddFile(file) 但 AddFile 方法不存在,因为 return 类型是我想要的 IRepository。但是我的 IRepositoryWithAttachement 正在扩展 IRepository 所以我很困惑我将如何到达它并且我设法做到了这一点:

 public string AddFile(Attachement file) {

 IExternalService eService = _externalServices.GetExternalService(id);

        try
        {                
                ((IRepositoryWithAttachement ) eService .Repository).AddFile(file); 
        }
        catch (Exception e)
        {               
           ...
        }
 }
}

问题 我这样做是错误的还是通过类型转换获取 addfile 方法的问题是一个丑陋的解决方案?

我看到的两个最大问题是 a) 您似乎在使用异常处理来防止存储库未实现您需要的接口,以及 b) 您正在捕获 Exception,而不是InvalidCastException and/or 其他 特定的 您可以正确预测和处理的异常。

恕我直言,更好的实现应该是这样的:

public string AddFile(Attachement file) {
    IExternalService eService = _externalServices.GetExternalService(id);
    IRepositoryWithAttachement repository = eService.Repository as IRepositoryWithAttachement;

    if (repository == null)
    {
        // report error in some appropriate way and return, or throw an
        // _informative_ exception, e.g.
        //     new NotSupportedException("repository does not support attachments")
    }

    repository.AddFile(file); 
}

更好的方法是对可用的存储库 ID 进行分类并根据功能限制访问,这样 AddFile() 方法就不会首先被调用,除非您知道存储库实现了必要的接口。然后你就可以安全地转换而不必担心抛出异常。


不幸的是,如果没有 a good, minimal, complete code example 清楚地说明问题,就很难或不可能提供比上述更具体的建议,并保证相关性。完全有可能有比您现在使用的方法更好的方法可用,但如果没有更多的上下文,就不可能真正说出那会是什么。