创建一个 returns 实现通用接口的对象的方法
Creating a method that returns an object implementing a generic interface
我有一个方法应该是 return 一个实现通用接口的对象。它接受一个参数,该参数确定要实例化哪个 class 和 return 实例化对象。
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);
}
"Player1" 和 "AnotherPlayer" 都实现了 IPlayer。
为什么我的方法在我的方法类型 "T" 下给出 "type or namespace 'T' could not be found" 错误?
在 return 类型是实现通用接口的对象的情况下,编写方法的正确方法是什么?
首先,您的 Retrieve
方法需要像 Retrieve<T>
这样的通用方法。那么问题就变成了,调用的时候需要指定T
的类型。如果您的 Player1
和 AnotherPlayer
没有实现相同的 IPlayer<T>
(意味着 T
不同),那么您将指定什么作为泛型的类型?
你可以做的是,创建一个 IPlayer
非通用接口,将所有非通用的东西移入其中,然后 IPlayer<T>
从那个接口继承,添加通用 properties/methods。然后,您的方法可以 return 非泛型 IPlayer
.
如果Player1
和AnotherPlayer
都实现了IPlayer
接口,则不需要使用泛型。如果您传入要实例化的对象类型而不是字符串 SitePath
,则可以使用反射来创建所需类型的对象。最简单的方法如下:
只需删除 return 类型上的 <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");
在上面的代码中,您只是错过了 PlayerRetriever
上的泛型。应该是PlayerRetriever<T>
。为了进一步扩展你所拥有的,你可以对你的泛型进行限制,使其只接受实现 IPlayer
的类型。约束是 where T : IPlayer<T>
。如果您尝试传递任何未实现 IPlayer
的东西,它就不起作用。这应该更接近您正在寻找的内容并修复了您的原始问题。
此外,如果您想 return 一个具体的 class 考虑使用 Activator 反射来创建您的 return 类型。那就是 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);
}
我有一个方法应该是 return 一个实现通用接口的对象。它接受一个参数,该参数确定要实例化哪个 class 和 return 实例化对象。
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);
}
"Player1" 和 "AnotherPlayer" 都实现了 IPlayer。
为什么我的方法在我的方法类型 "T" 下给出 "type or namespace 'T' could not be found" 错误?
在 return 类型是实现通用接口的对象的情况下,编写方法的正确方法是什么?
首先,您的 Retrieve
方法需要像 Retrieve<T>
这样的通用方法。那么问题就变成了,调用的时候需要指定T
的类型。如果您的 Player1
和 AnotherPlayer
没有实现相同的 IPlayer<T>
(意味着 T
不同),那么您将指定什么作为泛型的类型?
你可以做的是,创建一个 IPlayer
非通用接口,将所有非通用的东西移入其中,然后 IPlayer<T>
从那个接口继承,添加通用 properties/methods。然后,您的方法可以 return 非泛型 IPlayer
.
如果Player1
和AnotherPlayer
都实现了IPlayer
接口,则不需要使用泛型。如果您传入要实例化的对象类型而不是字符串 SitePath
,则可以使用反射来创建所需类型的对象。最简单的方法如下:
只需删除 return 类型上的 <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");
在上面的代码中,您只是错过了 PlayerRetriever
上的泛型。应该是PlayerRetriever<T>
。为了进一步扩展你所拥有的,你可以对你的泛型进行限制,使其只接受实现 IPlayer
的类型。约束是 where T : IPlayer<T>
。如果您尝试传递任何未实现 IPlayer
的东西,它就不起作用。这应该更接近您正在寻找的内容并修复了您的原始问题。
此外,如果您想 return 一个具体的 class 考虑使用 Activator 反射来创建您的 return 类型。那就是 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);
}