问题描述
这篇文章是基于我的原始文章从昨天开始。但是我对我的需求不够严谨,所以我会再试一次。
请查看我目前的代码:
public interface IPosterGenerator< T>
{
IQueryable< T> GetPosters();
}
公共类PetPosterGenerator:IPosterGenerator< PetPoster>
{
IQueryable< PetPoster> GetPosters()
{
return busLogic.GetPetPosters();
}
}
公共类FlowerPosterGenerator:IPosterGenerator< FlowerPoster>
{
IQueryable< FlowerPoster> GetPosters()
{
return busLogic.GetFlowerPosters();
}
}
公共类别PinBoard
{
受保护的列表< IPosterGenerator> PosterGenerators {get;组; } // 1.编译器错误
public PinBoard(List< IPosterGenerator>生成器)// 2.编译器错误
{
this.PosterGenerators = generators;
}
公共列表< BasePoster> GetPosters()
{
var posters = new List< BasePoster>();
foreach(PosterGenerators中的var生成器)
{
posters.Add(generator.GetPosters());
}
返回海报;
}
}
我的目标是创建一个PinBoard返回海报清单。每张海报可以是不同类型的(例如宠物海报,花海报等)。每张海报都有完全不同的外观,内容等等。但他们都继承了BasePoster类。
总而言之,我将拥有大约100种不同类型的海报。一个具体的PinBoard实例可以很容易地包含1000张海报和更多不同种类的海报(按照不同的顺序)。
为了填充某个PinBoard的海报,我需要给PinBoard提供一些海报生成器列表(发生器的数量和类型将根据上下文)。每个海报类型都会有一个海报生成器(例如,PetPosterGenerator可以生成一系列宠物海报)。
我认为如果我所有的海报生成器都可以共享相同的(类型安全的)接口。这就是为什么我引入了IPosterGenerator接口的原因。
我的问题是代码不能编译。有两个编译器错误带有相同的错误信息:使用泛型类型myApp.IPosterGenerator需要1个类型参数通过错误消息,因为我没有在这些位置定义任何类型。如果我可以在第一个错误的行中做这样的事情,那将是非常好的:
protected List< IPosterGenerator< T> > PosterGenerators {get;组; }
但是当我这样做时,编译器无法找到类型或名称空间T。
现在我有点迷路了。毕竟,使用通用的IPosterGenerator接口可能不是一个好主意。但我确信,在我的应用程序中的某个时刻,我需要知道或访问特定IPosterGenerator所代表的具体海报类型。
你们会怎么做?非常感谢您提前给予您的支持。
没有神奇的解决方案。如果你想使用泛型,你仍然需要使用它们。我的意思是你无法避免它们。另一方面,为了让 IPosterGenerator< T> 可以利用协方差 code>
T
参数接受 BasePoster
:
//在通用参数中检查out关键字!
//out使T参数协变。
public interface IPosterGenerator< out T>其中T:BasePoster
{
IQueryable< T> GetPosters();
}
现在您可以执行此操作:
public class PinBoard
{
protected List< IPosterGenerator< BasePoster>> PosterGenerators {get;组; }
$ b $ public PinBoard(List< IPosterGenerator< BasePoster>>生成器)
{
this.PosterGenerators = generators;
}
公共列表< BasePoster> GetPosters()
{
var posters = new List< BasePoster>();
foreach(PosterGenerators中的var生成器)
{
posters.Add(generator.GetPosters());
}
返回海报;
}
}
这么简单! :)
This post is based in my original post from yesterday. But I wasn't precise enough about my needs, so I will try again here.
Please see my current code:
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;
}
}
My goal is to create a "PinBoard" which can return a list of posters. Each poster can be of a different type (e.g. pet poster, flower poster, etc.). Every poster has a totally different look, content and so on. But they all inherit from a BasePoster class.
All in all I am going to have about 100 different types of posters. A concrete PinBoard instance can easily contain 1000 posters and more of all different kinds of posters (in diverse order).
In order to populate the posters of a certain PinBoard, I need to feed the PinBoard with a list of certain poster generators (the amount and type of generators will change based on the context). There will be one poster generator per poster type (e.g. the PetPosterGenerator which generates a collection of pet posters).
I thought it would be nice if all my poster generators could share the same (type safe) interface. That's why I introduced the IPosterGenerator interface.
My problem is that the code does not compile. There are two compiler errors with the same error message: Using the generic type 'myApp.IPosterGenerator' requires 1 type arguments
I am not surprised by the error message because I am not defining any type at these locations. It would be great if I could do something like this in the line of the first error:
protected List<IPosterGenerator<T>> PosterGenerators { get; set; }
But when I do this, the compiler can't find type or namespace T.
Now I am kind of lost. Maybe using the generic IPosterGenerator interface is not such a good idea after all. But I am sure that at some point in my application I need to know or access the concrete poster type which a certain IPosterGenerator represents.
How would you guys approach this? Thank you very much for your support in advance.
There's no magic solution. If you want to use generics, you still need to use them. I mean that you can't avoid them.
In the other hand, you can take advantage of covariance in order to let the IPosterGenerator<T>
T
parameter accept 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();
}
Now you can do this:
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;
}
}
So easy! :)
这篇关于使用通用接口列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!