这篇文章是基于我昨天的original post。但我对自己的需求不够精确,所以我会在这里再试一次。
请查看我的当前代码:
public interface IPosterGenerator<T>
{
IQueryable<T> GetPosters();
}
public class PetPosterGenerator : IPosterGenerator<PetPoster>
{
IQueryable<PetPoster> GetPosters()
{
return busLogic.GetPetPosters();
}
}
public class FlowerPosterGenerator : IPosterGenerator<FlowerPoster>
{
IQueryable<FlowerPoster> GetPosters()
{
return busLogic.GetFlowerPosters();
}
}
public class PinBoard
{
protected List<IPosterGenerator> PosterGenerators { get; set; } // 1. compiler error
public PinBoard(List<IPosterGenerator> generators) // 2. compiler error
{
this.PosterGenerators = generators;
}
public List<BasePoster> GetPosters()
{
var posters = new List<BasePoster>();
foreach (var generator in PosterGenerators)
{
posters.Add(generator.GetPosters());
}
return posters;
}
}我的目标是创建一个"PinBoard“,它可以返回海报列表。每一张海报可以是不同类型的(例如宠物海报、花卉海报等)。每一张海报都有一个完全不同的外观,内容等等。但是它们都是从BasePoster类继承的。
总之,我将有大约100种不同类型的海报。一个具体的PinBoard实例可以很容易地包含1000个海报和更多不同类型的海报(按不同的顺序排列)。
为了填充某个PinBoard的海报,我需要向PinBoard提供一个特定的海报生成器列表(生成器的数量和类型将根据上下文变化)。每个海报类型将有一个海报生成器(例如,生成宠物海报集合的PetPosterGenerator )。
我想如果我所有的海报生成器都能共享相同的(类型安全)接口,那就太好了。这就是为什么我引入了IPosterGenerator接口。
我的问题是代码没有编译。有两个带有相同错误消息的编译器错误:使用泛型类型'myApp.IPosterGenerator‘需要一个类型参数
我对错误消息并不感到惊讶,因为我没有在这些位置定义任何类型。如果我能在第一个错误行中这样做,那就太好了:
protected List<IPosterGenerator<T>> PosterGenerators { get; set; }但是当我这样做时,编译器找不到类型或命名空间T。
现在我有点迷茫了。也许使用通用的IPosterGenerator接口毕竟不是一个好主意。但我确信,在我的应用程序中的某个时刻,我需要知道或访问某个IPosterGenerator所代表的具体的海报类型。
你们怎么处理这件事?非常感谢你事先给予的支持。
发布于 2013-02-19 16:25:28
没有神奇的解决办法。如果您想使用泛型,您仍然需要使用它们。我是说你躲不了他们。
另一方面,您可以利用协方差让IPosterGenerator<T> T参数接受BasePoster。
// Check the "out" keyword in the generic parameter!
// "out" makes the T parameter covariant.
public interface IPosterGenerator<out T> where T : BasePoster
{
IQueryable<T> GetPosters();
}现在你可以这样做了:
public class PinBoard
{
protected List<IPosterGenerator<BasePoster>> PosterGenerators { get; set; }
public PinBoard(List<IPosterGenerator<BasePoster>> generators)
{
this.PosterGenerators = generators;
}
public List<BasePoster> GetPosters()
{
var posters = new List<BasePoster>();
foreach (var generator in PosterGenerators)
{
posters.Add(generator.GetPosters());
}
return posters;
}
}很简单!:)
发布于 2013-02-19 16:16:20
您通常会定义一个非泛型接口,然后使您的泛型接口继承它。就像这样:
public interface IPosterGenerator
{
IQueryable GetPosters();
}
public interface IPosterGenerator<T> :
IPosterGenerator
{
new IQueryable<T> GetPosters();
}要实现这个接口,您可以执行以下操作
public class PetPosterGenerator :
IPosterGenerator<PetPoster>
{
IQueryable<PetPoster> GetPosters()
{
return busLogic.GetPetPosters();
}
// Explicit interface implementation on non-generic method
IQueryable IPosterGenerator.GetPosters()
{
// Invokes generic version
return this.GetPosters();
}
}发布于 2013-02-19 16:28:25
使用泛型是可能的:
public abstract class BasePoster { }
public class PetPoster : BasePoster { }
public class FlowerPoster : BasePoster { }
// NOTE the out keyword here.
public interface IPosterGenerator<out T> where T : BasePoster
{
IQueryable<T> GetPosters();
}
public class PetPosterGenerator : IPosterGenerator<PetPoster>
{
public IQueryable<PetPoster> GetPosters()
{
return Enumerable.Range(0, 5).Select(i =>
{
return new PetPoster();
}).AsQueryable();
}
}
public class FlowerPosterGenerator : IPosterGenerator<FlowerPoster>
{
public IQueryable<FlowerPoster> GetPosters()
{
return Enumerable.Range(0, 5).Select(i =>
{
return new FlowerPoster();
}).AsQueryable();
}
}
public class PinBoard
{
protected List<IPosterGenerator<BasePoster>> PosterGenerators
{
get;
private set; // fixes compiler warning #1
}
public PinBoard(List<IPosterGenerator<BasePoster>> generators) // specify the generic type, fixes compiler warning #2
{
this.PosterGenerators = generators;
}
public List<BasePoster> GetPosters()
{
var posters = new List<BasePoster>();
foreach (var generator in PosterGenerators)
{
posters.AddRange(generator.GetPosters()); // call AddRange not Add
}
return posters;
}
}然后这就起作用了:
var generators = new List<IPosterGenerator<BasePoster>>();
generators.Add(new FlowerPosterGenerator());
generators.Add(new PetPosterGenerator());
var pinBoard = new PinBoard(generators);https://stackoverflow.com/questions/14962110
复制相似问题