【问题标题】:Create factory that will return object of generic abstract type in .net core创建将在 .net 核心中返回通用抽象类型对象的工厂
【发布时间】:2018-11-20 21:54:27
【问题描述】:

我正在创建使用抽象泛型类作为基础的代码。我有点卡住了,因为我试图创建将根据插入的对象类型返回特定对象的工厂。

假设我想与对象进行比较以检查它们是否相等。在我的场景中,如果它们是IEnumerableIList 的类型,我想以这种方式比较对象

我的代码:

界面:

public interface IObjectComparer<in T>
{
    bool Compare(T obj1, T obj2);
}

基类:

public abstract class ObjectComparerBase<T> : IObjectComparer<T>
{
    public abstract bool Compare(T obj1, T obj2);

    public void SomeUsefullHelperMethod()
    {

    }
}

IList 对象比较器:

public sealed class ListObjectComparer : ObjectComparerBase<IList>
{
    public override bool Compare(IList obj1, IList obj2)
    {
        throw new NotImplementedException();
    }
}

IEnumerable对象比较器

public sealed class EnumerableObjectComparer : ObjectComparerBase<IEnumerable>
{ 
    public override bool Compare(IEnumerable obj1, IEnumerable obj2)
    {
        throw new System.NotImplementedException();
    }
}

最后我的工厂应该决定是否需要为某个对象使用哪个比较器:

public sealed class ComparerRetriever
{
    public static IObjectComparer<T> Retrieve<T>(T obj)
    {
        IObjectComparer<T> comparer = null;
        switch (typeof(T))
        {
            case IEnumerable o:
            {
                comparer = new EnumerableObjectComparer();
                break;
            }

            case IList o:
            {
                comparer = new ListObjectComparer();
                break;
            }

            default:
                throw new NotSupportedException("Not Supported Type");
        }

        return comparer;
    }
}

我的问题:

在当前情况下,我不能使用我的 ComparerRetriever 类,因为编译器说下界 ListObjectComparerEnumerableObjectComparer 不是 IObjectComparer&lt;T&gt; 类型。

我的问题是为什么?我的对象有 ObjectComparerBase&lt;T&gt; 类作为父类,而这个类正在实现 IObjectComparer&lt;T&gt; 所以在我看来 EnumerableObjectComparerListObjectComparer 应该是 ObjectComparerBase&lt;T&gt; 的类型

可能我遗漏了一些东西,但此时我看不到什么。

你能帮帮我吗?

谢谢。

【问题讨论】:

  • 不幸的是,编译器不理解Tcase 的类型和您构造的类型之间的联系。假设类型确实匹配,构造和返回它们的唯一方法是执行return (IObjectComparer&lt;T&gt;)(object)new EnumerableObjectComparer();(我相信object 的中间转换是必要的,但不要尝试)
  • 这个演员阵容在这种情况下很有帮助。我也需要这个中期演员。我认为这是一个很好的答案。也许这个演员的代码看起来不是最好的,但至少我直到编译。

标签: c# generics .net-core


【解决方案1】:

所以这可以正常工作并按预期返回类。你必须把 IList 放在第一位,因为 IList 实现了 IEnumerable,如果 IEnumerable 是第一位的,它也属于这种情况。

public sealed class ComparerRetriever
{
    public static IObjectComparer<T> Retrieve<T>(T obj)
    {
        IObjectComparer<T> comparer;
        switch (typeof(T))
        {
            case IList o:
            {
                comparer = new ListObjectComparer() as IObjectComparer<T>;
                break;
            }
            case IEnumerable o:
            {
                comparer = new EnumerableObjectComparer() as IObjectComparer<T>;
                break;
            }


            default:
                throw new NotSupportedException("Not Supported Type");
        }

        return comparer;
    }
}

我确实认为,您将始终使用默认情况作为传递给 Retrieve 方法的任何对象,因为它将具有具体类型,而 typeof 将导致该具体类型而不是 Intreface

例如,当我进行测试时,我创建了

class SimpleList : IList
{
   ... blah
}

并且可以预见的是,typeof 调用会导致 SimpleList 而不是 IList,所以它总是抛出

NotSupportedException("Not Supported Type");

显然我可能是错的,你可能比我领先一步,所以我将把答案留在那里,因为我相信我已经回答了最初的问题

更新 经过更多测试后,我不确定您是否可以在接口上使用模式匹配,因此我已将实现更改为以下内容,但仍然使用默认情况。

public static IObjectComparer<T> Retrieve<T>(T obj)
{
    IObjectComparer<T> comparer;

    var interf = typeof(T).GetInterfaces().FirstOrDefault();
    switch (interf)
    {
        case IList o:
        {
            comparer = new ListObjectComparer() as IObjectComparer<T>;
            break;
        }
        case IEnumerable o:
        {
            comparer = new EnumerableObjectComparer() as IObjectComparer<T>;
            break;
        }


        default:
            throw new NotSupportedException("Not Supported Type");
    }

    return comparer;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-05
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    相关资源
    最近更新 更多