C# 定义实现泛型的接口依赖项
这将是泛型101为许多,但下面是示例代码,所以我可以更好地理解C# 定义实现泛型的接口依赖项,c#,.net,generics,C#,.net,Generics,这将是泛型101为许多,但下面是示例代码,所以我可以更好地理解 public interface IRecordedItemsProcessor<T> { ObservableCollection<RecordedItem> Load(string name); void Save(); RecordedItem Parse(T itemToParse); } public class FileLoadingProcessor : IRecord
public interface IRecordedItemsProcessor<T>
{
ObservableCollection<RecordedItem> Load(string name);
void Save();
RecordedItem Parse(T itemToParse);
}
public class FileLoadingProcessor : IRecordedItemsProcessor<string>
{
public ObservableCollection<RecordedItem> Load(string name)
{
}
public void Save()
{
}
public RecordedItem Parse(string itemToParse)
{
}
}
public class MyClass
{
public MyClass(IRecordedItemsProcessor<T> processor)
{
}
}
公共接口IRecordedItemsProcessor
{
ObservableCollection负载(字符串名称);
作废保存();
recordeditemparse(T itemToParse);
}
公共类文件加载处理器:IRecordedItemsProcessor
{
公共ObservableCollection加载(字符串名称)
{
}
公共作废保存()
{
}
public RecordedItem Parse(string itemToParse)
{
}
}
公共类MyClass
{
公共MyClass(IRecordedItemsProcessor处理器)
{
}
}
问题是,MyClass
需要依赖于IRecordedItemsProcessor
,但不会编译,因为它不知道T
是什么。如何解决这个问题?让MyClass实现a似乎有些奇怪,因为它所需要做的只是调用Load/Save
谢谢第一个解决方案是最简单的:将泛型声明提升到类级别,如
public class MyClass<T>
{
public MyClass(IRecordedItemsProcessor<T> processor)
{
}
}
第二种解决方案是从构造函数中删除泛型输入并推断类型。然后,您不需要精确地从调用中指定泛型。类声明如下所示:
public class MyClass
{
public void Process<T>(IRecordedItemsProcessor<T> processor)
{
}
}
其思想是,您总是需要显式地指定类级泛型,但方法级泛型可以由编译器推断出来
第三种解决方案是将创建机制封装在MyClassFactory
中。这是非常灵活的,但它可能看起来有点复杂,因为IRecordeditMSProcessor
的后代不在类级别定义泛型,所以我们应该转到实现的接口并获取泛型类型。只有这样,我们才能构造泛型MyClass
。清单如下:
public class MyClassFactory
{
public MyClass<T> MakeMyClassFor<T>(IRecordedItemsProcessor<T> processor)
{
var processorGenericType = processor.GetType()
.GetInterfaces()
.Single(intr=>intr.Name == "IRecordedItemsProcessor`1")
.GetGenericArguments()[0];
var myClassType = typeof(MyClass<>).MakeGenericType(processorGenericType);
return Activator.CreateInstance(myClassType, processor) as MyClass<T>;
}
}
这三种方法各有利弊。考虑一下你将要使用的上下文。 第一个解决方案是最简单的:将泛型声明提升到类级别,如
public class MyClass<T>
{
public MyClass(IRecordedItemsProcessor<T> processor)
{
}
}
第二种解决方案是从构造函数中删除泛型输入并推断类型。然后,您不需要精确地从调用中指定泛型。类声明如下所示:
public class MyClass
{
public void Process<T>(IRecordedItemsProcessor<T> processor)
{
}
}
其思想是,您总是需要显式地指定类级泛型,但方法级泛型可以由编译器推断出来
第三种解决方案是将创建机制封装在MyClassFactory
中。这是非常灵活的,但它可能看起来有点复杂,因为IRecordeditMSProcessor
的后代不在类级别定义泛型,所以我们应该转到实现的接口并获取泛型类型。只有这样,我们才能构造泛型MyClass
。清单如下:
public class MyClassFactory
{
public MyClass<T> MakeMyClassFor<T>(IRecordedItemsProcessor<T> processor)
{
var processorGenericType = processor.GetType()
.GetInterfaces()
.Single(intr=>intr.Name == "IRecordedItemsProcessor`1")
.GetGenericArguments()[0];
var myClassType = typeof(MyClass<>).MakeGenericType(processorGenericType);
return Activator.CreateInstance(myClassType, processor) as MyClass<T>;
}
}
这三种方法各有利弊。考虑一下你将要使用的上下文。 您可以执行以下操作:
var myClass = new MyClass<string>(new FileLoadingProcessor());
Console.WriteLine (myClass);
IRecordedItemsProcessor
(非通用)Load
和Save
移动到此IRecordedItemsProcessor
IRecordedItemsProcessor
从此IRecordedItemsProcessor
MyClass
expectIRecordedItemsProcessor
在其构造函数中这清楚地表明,
MyClass
不关心处理器可以解析什么类型的东西,甚至根本不关心它可以解析什么东西——它只知道它可以保存和加载。您可以执行以下操作:
var myClass = new MyClass<string>(new FileLoadingProcessor());
Console.WriteLine (myClass);
IRecordedItemsProcessor
(非通用)Load
和Save
移动到此IRecordedItemsProcessor
IRecordedItemsProcessor
从此IRecordedItemsProcessor
MyClass
expectIRecordedItemsProcessor
在其构造函数中这清楚地表明,
MyClass
不关心处理器可以解析什么类型,甚至根本不关心它可以解析东西——它只知道它可以保存和加载。泛型类型,如所写,正在MyClass
构造函数上声明,这意味着必须在MyClass
级别定义泛型类型:
public class MyClass<T>
{
public MyClass(IRecordedItemsProcessor<T> processor)
{
}
}
公共类MyClass
{
公共MyClass(IRecordedItemsProcessor处理器)
{
}
}
但是,如果泛型类型是在方法级别声明的,则只需在方法级别定义它:
public class MyClass
{
public void MyMethod<T>( IRecordedItemsProcessor<T> processor )
{
}
}
公共类MyClass
{
public void MyMethod(IRecordedItemsProcessor处理器)
{
}
}
编辑根据您的评论: 我想要一个可以调用Load/Save方法但不必担心的类 那不是 然后需要两个接口:一个用于加载/保存,另一个用于解析。在这种情况下,您可以使用继承:
public interface IRecordedItems
{
ObservableCollection<RecordedItem> Load( string name );
void Save();
}
public interface IRecordedItemsProcessor<T> : IRecordedItems
{
RecordedItem Parse( T itemToParse );
}
public class MyClass : IRecordedItems
{
#region Implementation of IRecordedItems
public ObservableCollection<RecordedItem> Load( string name )
{
throw new NotImplementedException();
}
public void Save()
{
throw new NotImplementedException();
}
#endregion
}
公共接口IRecordedItems
{
ObservableCollection负载(字符串名称);
作废保存();
}
公共接口IRecordedItems处理器:IRecordedItems
{
recordeditemparse(T itemToParse);
}
公共类MyClass:IRecordedItems
{
#IRecordedItems的区域实现
公共ObservableCollection加载(字符串名称)
{
抛出新的NotImplementedException();
}
公共作废保存()
{
抛出新的NotImplementedException();
}
#端区
}
编辑2根据您的选择,可以将类型依赖项从接口中移出,直接移到接口方法中:
public class RecordedItem {}
public interface IRecordedItemsProcessor
{
ObservableCollection<RecordedItem> Load( string name );
void Save();
RecordedItem Parse<T>( T itemToParse );
}
public class MyClass
{
private readonly IRecordedItemsProcessor _processor;
public MyClass( IRecordedItemsProcessor processor )
{
_processor = processor;
processor.Parse<string>( "foo" );
processor.Parse<int>( 10 );
processor.Parse<RecordedItem>( new RecordedItem() );
}
}
公共类RecordedItem{}
公共接口IRecordedItemsProcessor
{
ObservableCollection负载(字符串名称);
作废保存();
recordeditemparse(T itemToParse);
}
公共类MyClass
{
专用只读IRecordedItemsProcessor\u处理器;
公共MyClass(IRecordedItemsProcessor处理器)
{
_处理机=