C# 如何正确处理由泛型类和具有泛型返回的方法组成的列表
我相信这个问题的答案很简单,但由于我已经在这个问题上绞尽脑汁了一段时间,我可能很难看清全局 我想加载多个文件(在本例中为JSON),因此我创建了一个C# 如何正确处理由泛型类和具有泛型返回的方法组成的列表,c#,json,generics,interface,abstract-class,C#,Json,Generics,Interface,Abstract Class,我相信这个问题的答案很简单,但由于我已经在这个问题上绞尽脑汁了一段时间,我可能很难看清全局 我想加载多个文件(在本例中为JSON),因此我创建了一个DataLoader类来处理这个问题。在这个类中,我创建了一个类将迭代和加载的iloader列表,这样将来如果我使用JSON以外的东西,抽象就已经实现了 public class DataLoader{ private List<IDataLoaded> allDataLoaded = new List<IDataLoad
DataLoader
类来处理这个问题。在这个类中,我创建了一个类将迭代和加载的iloader
列表,这样将来如果我使用JSON以外的东西,抽象就已经实现了
public class DataLoader{
private List<IDataLoaded> allDataLoaded = new List<IDataLoaded>();
private List<ILoader> loaderLists = new List<ILoader> (){
new JSONLoader<RootSpacecrafts>(),
new JSONLoader<RootWeapons>()
};
public void LoadData(){
foreach(ILoader loader in loaderLists){
loader.Read ();
IDataLoaded dataLoaded = loader.Load ();
allDataLoaded.Add(dataLoaded);
}
}
}
以及ILoader:
public interface ILoader<T>{
void Read();
List<T> Load();
}
公共接口ILoader{
无效读取();
列表加载();
}
现在,当我回到DataLoader
类时,正如您所看到的,我失去了调用ILoader
的灵活性,因为我需要告诉您使用的泛型类是什么
我试图将其封装在另一个接口中,但是DataLoader
中的loader.Load()
调用被中断,因为它返回一个列表
现在我觉得,如果要在一边修好,我会打破另一边。我一直在尝试将抽象类和接口很好地结合起来,以相应地隔离所有内容,但我在可视化所有内容时遇到了很大的困难(我对C#还相当陌生,还没有足够的思维敏捷性来了解我应该做什么和封装)
我将此作为学习C#的练习,并希望尽可能使用最佳编程实践。我希望有一个健壮的代码,没有重复,并且类之间的依赖关系最少。我还希望得到一个解释,而不仅仅是一个工作代码。谢谢大家!
我对接口有一些问题(它抱怨它不能
将JSONLoader表达式转换为类型
ILoader)
这是因为List
不是协变的。如果您希望这样做,而不是公开列表
,您可以公开在T
中协变的IEnumerable
,还可以使您的加载器
与加载器
协变:
公共类数据加载器
{
private IEnumerable allDataLoaded=新列表();
私有IEnumerable LoaderList=新建
列表
{
新的JsonLoader(),
新的JsonLoader()
};
公共void LoadData()
{
foreach(装载机列表中的ILoader装载机)
{
loader.Read();
allDataLoaded=loader.Load();
}
}
}
公共接口ILoader
{
无效读取();
IEnumerable Load();
}
公共类JsonLoader:ILoader,其中T:IDataLoaded,new()
{
私有字符串文件内容;
私有T输出=新T();
私有IEnumerable输出列表;
公共无效读取()
{
fileContents=File.ReadAllText(“”);
outputlist=JsonConvert.DeserializeObject(fileContents);
}
公共IEnumerable负载()
{
返回输出列表;
}
}
您在ILoader
中有T
的哪些用法?仅用于加载值?另外,我假设RootSpacecrafts
和rootwearms
实现IDataLoaded
?T
用于将json反序列化为正确的根类,并返回反序列化数据的相应列表。是的,它们实现了IDataLoaded
。目前,这只是为了获取JSON文件的路径,它是根类的一个属性。迭代foreach(LoaderList中的ILoader loader)
应该会给您带来您想要的灵活性,不是吗?非常感谢您的帮助和时间,Yuval:)根据我的理解,协变类型参数“t”必须在“ILoader.Load()”上始终有效,在界面中同时使用协方差和逆变方差时会发生这种情况。但ILoader似乎是协变的,而不是反变的。你知道这里的冲突是什么吗?如果T
是协变的,它不能作为输入参数传递给ILoader
中的方法。我需要实例化它以获得具有文件路径的属性。它看起来很难看,但我希望一旦我开始工作,它会组织得更好。再次感谢你的帮助!只是一个更新:因为我当前使用的是Unity,所以IEnumerable似乎不是协变的:公共接口IEnumerable:IEnumerable
,因此出现了错误。尽管如此,这是了解协方差有用性的一个很好的练习!
public interface ILoader<T>{
void Read();
List<T> Load();
}
public class DataLoader
{
private IEnumerable<IDataLoaded> allDataLoaded = new List<IDataLoaded>();
private IEnumerable<ILoader<IDataLoaded>> loaderLists = new
List<ILoader<IDataLoaded>>
{
new JsonLoader<RootSpacecrafts>(),
new JsonLoader<RootWeapons>()
};
public void LoadData()
{
foreach (ILoader<IDataLoaded> loader in loaderLists)
{
loader.Read();
allDataLoaded = loader.Load();
}
}
}
public interface ILoader<out T>
{
void Read();
IEnumerable<T> Load();
}
public class JsonLoader<T> : ILoader<T> where T : IDataLoaded, new()
{
private string fileContents;
private T output = new T();
private IEnumerable<T> outputlist;
public void Read()
{
fileContents = File.ReadAllText("");
outputlist = JsonConvert.DeserializeObject<List<T>>(fileContents);
}
public IEnumerable<T> Load()
{
return outputlist;
}
}