如何使用通用基类实现服务定位器模式?

时间:2012-06-28 13:36:37

标签: c# generics

我已经陷入困境22,似乎无法找到出路。我正在尝试实现一个简单的[Service Locator] [1],由下面的示例代码中的GetInstance方法表示。现在的问题是我在return语句中遇到编译器错误:

Cannot implicitly convert type 'Cyberspace.SubClass' to 'Cyberspace.BaseClass<T>'

我已经尝试过重写,以便SubClass本身就是泛型类,但是后来我在DoSomething方法的return语句中遇到了编译器错误。

任何人都可以编译此代码,保留Service Locator模式原则,允许我在GetInstace方法中使用抽象返回类型吗?或者我想在这里尝试一些不可能的东西?

namespace Cyberspace
{
    class BaseClass<T>
    {
        BaseClass<T> GetInstance() 
        { 
            return new SubClass();
        }
        virtual T DoSomething() { return default(T); }          
    }

    class SubClass : BaseClass<OtherClass>
    {
        public override OtherClass DoSomething()
        { 
            var other = new OtherClass { Description = "Generics are hard"};
            return other;
        }
    }

    class OtherClass
    {
        internal string Description { get; set; }
    }
}

尝试2:

namespace Cyberspace
{
    class BaseClass<T>
    {
        static BaseClass<T> GetInstance() // The "Service Locator" method
        { 
            return new SubClass<T>(); 
        }
        internal virtual T DoSomething() { return default(T); }        
    }

    class SubClass<T> : BaseClass<T> where T: OtherClass
    {
        internal override T DoSomething()
        { 
            var other = new OtherClass { Description = "Generics are hard"};
            return (T) other;
        }
    }

    class OtherClass
    {
        internal string Description { get; set; }
    }
}

这会在return new SubClass<T>();

上产生以下错误

The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Cyberspace.SubClass<T>'. There is no boxing conversion or type parameter conversion from 'T' to 'Cyberspace.OtherClass'

2 个答案:

答案 0 :(得分:3)

我不清楚你真正想要做什么,但我可以告诉你为什么会发生编译错误。

从此方法返回的任何内容:

BaseClass<T> GetInstance()

必须能够处理任何类型T(因为您没有类型约束)。 SubClass只能处理一种类型,而不是所有类型。因此你无法退货。

答案 1 :(得分:1)

当使用类型参数T时,你声明:“我不关心这个类型究竟是什么。我只需要一些类型,任何类型都可以。调用它{{ 1}}。“。但在你的情况下,你看起来想要一个特定的类型。那么就不需要泛型了。

T

为什么以下不起作用?

class SubClass : BaseClass<OtherClass>
{
    internal override OtherClass DoSomething()
    { 
        var other = new OtherClass { Description = "Generics are hard"};
        return other;
    }
}

因为 var other = new OtherClass { Description = "Generics are hard"}; return (T) other; 可能来自T。您无法将OtherClass转换为从OtherClass派生的类。没有任何意义,编译器足够聪明,可以捕获它。

<小时/> 评论中的讨论导致以下解决方法:

OtherClass

当然,只有在运行时排列类型时,这才有效。