创建一个返回实现通用接口的对象的方法

时间:2015-01-29 20:40:48

标签: c# asp.net oop

我有一个方法可以返回实现通用接口的对象。它接受一个参数来确定实例化哪个类并返回实例化的对象。

    public class PlayerRetriever
    {
        public static IPlayer<T> Retrieve(string SitePath)
        {
            if (SitePath == "Home") { return new Player1(); }
            else { return new AnotherPlayer(); }
        }
    }
    interface IPlayer<T>
    {
        void RunPlayer();
        List<T> RetrievePlayersByMovie(string movie);
    }

两者&#34; Player1&#34;和#34; AnotherPlayer&#34;实施IPlayer。

为什么我的方法会给我&#34;类型或命名空间&#39; T&#39;无法找到&#34; &#34; T&#34;下的错误在我的方法类型?

编写一种方法的正确方法是什么,其中返回类型是实现通用接口的对象?

3 个答案:

答案 0 :(得分:6)

对于初学者,您的Retrieve方法必须是通用的,如Retrieve<T>。然后问题变成,当你调用它时,你需要指定T的类型。如果您的Player1AnotherPlayer未实现相同的IPlayer<T>(意味着T不同),那么您将指定什么作为通用的类型?

您可以做的是,创建一个IPlayer非泛型接口,在其中将所有非泛型内容移动到其中,然后IPlayer<T>从该接口继承,添加通用属性/方法。然后,您的方法可以返回非泛型IPlayer

答案 1 :(得分:4)

如果Player1AnotherPlayer都实现了IPlayer接口,则无需使用泛型。如果您传入要实例化的对象类型而不是字符串SitePath,则可以使用反射来创建所需类型的对象。最简单的方法如下:

只需删除返回类型中的<T>部分即可。

public class PlayerRetriever
{
    public static IPlayer Retrieve(string SitePath)
    {
        if (SitePath == "Home") { return new Player1(); }
        else { return new AnotherPlayer(); }
    }
}

如果您需要访问特定于实现的属性,只需将其强制转换为原始类型:

AnotherPlayer castObject = (AnotherPlayer)returnedValue;

编辑 - 通用接口解决方案

由于您的IPlayer<T>界面使用泛型,因此解决方案如下:

public IPlayer<T> Retrieve<T>(string SitePath)
{
    if (SitePath == "Home") { return new Player1<T>(); }
    else { return new AnotherPlayer<T>(); }
}

然后你会这样称呼它,但用string类型代替代码所需的类型:

IPlayer<string> player = PlayerRetriever.Retrieve<string>("Home");

答案 2 :(得分:0)

在上面的代码中,您错过了PlayerRetriever上的通用广告。它应该是PlayerRetriever<T>。为了进一步提供你所拥有的东西,你可以对你的泛型加上约束,只接受一个实现IPlayer的类型。约束为where T : IPlayer<T>。如果您尝试传递任何未实现IPlayer的内容,则无效。这应该更接近您正在寻找的内容并修复您的原始问题。

另外,如果要返回具体类,请考虑在反射中使用Activator来创建返回类型。那就是T myClass = Activator.CreateInstance<T>();

public class PlayerRetriever<T>
    where T : IPlayer<T>
{
    public static IPlayer<T> Retrieve(string SitePath)
    {
        if (SitePath == "Home") { return new Player1(); }
        else { return new AnotherPlayer(); }
    }
}

interface IPlayer<T>
{
    void RunPlayer();
    List<T> RetrievePlayersByMovie(string movie);
}