【问题标题】:Get Concrete Implementation of Interface with Generic Parameter使用通用参数获取接口的具体实现
【发布时间】:2015-09-02 21:42:06
【问题描述】:

我现在感觉很愚蠢。不知道为什么我不能解决这个问题。我有一个存储库接口:

public interface ICollateralItemBaseImplementation<T> where T : CollateralItemBase
{
    int Add(T collateralItem);
    T Get(int collateralID);
}

和许多实现,每个实现从CollateralItemBase 继承的 10 个模型之一。例如:

internal sealed class CollateralItemCertifiedDepositRepository : ServiceBaseRepository, ICollateralItemBaseImplementation<CollateralItemCertifiedDeposit>
{
   int Add(CollateralItemCertifiedDeposit collateralItem) { /*...*/ }
   CollateralItemCertifiedDeposit Get(int collateralID)  { /*...*/ }
}  

现在我只需要打开传入的CollateralItemBase 类型即可获取我需要的存储库:

private ICollateralItemBaseImplementation<???> GetRepository(CollateralItemBase item) 
{
    switch (item.GetType().Name)
    {
            case "CollateralItemCertifiedDeposit": return new CollateralItemCertifiedDepositRepository();
            //...
    }

我只需要弄清楚从这个方法返回什么,以便其他方法作用于我返回的任何存储库。我如何重构它以使其正常工作? 我很确定我有协方差/逆变问题。再一次,我觉得自己很愚蠢,只是画了一个空白。

谢谢。

【问题讨论】:

  • 不应该GetRepository是一个泛型方法,这样你就可以将类型作为参数传递,而不是传递一个除了通过反射检查类型之外你不会访问的对象吗?跨度>
  • 它可能。但在我的应用程序 (wpf) 中,我实际上从来不需要自己操作真实类型。我使用模板选择器为实际类型获取正确的模板,并且绑定“神奇”地工作而无需我进行强制转换。所以在我所有的 ViewModel 中,我都在使用 CollateralItemBase 类型

标签: c# generics interface abstraction


【解决方案1】:

您可以分两个阶段完成。向ICollateralItemBaseImplementation 添加一个非泛型基接口,然后转换为泛型版本。

public interface ICollateralItemBaseImplementation
{
}

public interface ICollateralItemBaseImplementation<T> : ICollateralItemBaseImplementation
    where T : CollateralItemBase
{
    int Add(T collateralItem);
    T Get(int collateralID);
}

public static class RepositoryFactory
{
    public static ICollateralItemBaseImplementation<T> GetRepository<T>(T item)
        where T : CollateralItemBase
    {
        return (ICollateralItemBaseImplementation<T>)GetRepositoryImpl(item);
    }

    private static ICollateralItemBaseImplementation GetRepositoryImpl<T>(T item)
            where T : CollateralItemBase
    {
        switch (item.GetType().Name)
        {
            case "CollateralItemCertifiedDeposit":
                return new CollateralItemCertifiedDepositRepository();
        }
        return null;
    }
}

internal static class Program
{

    static void Main()
    {
        var repo = RepositoryFactory.GetRepository(new CollateralItemCertifiedDeposit());
        Debug.Assert(repo is CollateralItemCertifiedDepositRepository);

    }
}

【讨论】:

  • 谢谢科林。我想我必须以某种方式拥有一个非通用接口才能使类型正常工作。这为我修好了
【解决方案2】:

基本类型的通用返回参数怎么样

private ICollateralItemBaseImplementation<T>     GetRepository(CollateralItemBase item)  where T : ServiceBaseRepository
{
switch (item.GetType().Name)
{
        case "CollateralItemCertifiedDeposit": return new CollateralItemCertifiedDepositRepository();
        //...
}

【讨论】:

  • 那不会编译。首先T应该是CollateralItemBase类型其次,CollateralItemCertifiedDepositRepository没有实现ICollateralItemBaseImplementation&lt;T&gt;,它只实现了ICollateralItemBaseImplementation&lt;CollateralItemCertifiedDeposit &gt;,所以当你尝试返回它时你会得到一个错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-12
  • 1970-01-01
  • 2021-03-08
  • 1970-01-01
相关资源
最近更新 更多