如何在不通知父类泛型类型的情况下对注入的类调用泛型方法
本文关键字:情况下 注入 泛型方法 调用 泛型类型 通知 父类 | 更新日期: 2023-09-27 17:59:55
下面是注入到另一个类中的依赖项的实现。
public class CsvDataProvider : ICsvDataProvider
{
readonly ICsvReaderFactory _factory;
public CsvDataProvider(ICsvReaderFactory factory)
{
_factory = factory;
}
public IEnumerable<TRecord> GetData<TRecord>(string filepath) where TRecord : class
{
var reader = _factory.CreateCsvReader(filepath);
return reader.GetRecords<TRecord>();
}
}
factory
创建的reader
将读取CSV文件中的所有行,并将每行转换为TRecord
的实例。我不拥有reader
代码,也不能更改GetRecords<TRecord>()
方法。
这就是我陷入困境的地方:
public class CsvDataMigrationController
{
readonly ICsvDataProvider _provider;
readonly ICsvDataMigration _migration;
public CsvDataMigrationController(ICsvDataProvider provider, ICsvDataMigration migration)
{
_provider = provider;
_migration = migration;
}
public void ProcessFile(string path)
{
var records = _provider.GetData<I_DONT_WANT_TO_EXPLICITLY_SAY>(path); //<-- Help!
_migration.Migrate(records);
}
}
其目的是向CsvDataMigrationController
中注入一个数据提供程序和一个迁移过程类。控制器将调用数据提供程序来获取数据,并将数据传递到迁移类中。
- 我不想让
CsvDataMigrationController
知道所涉及的数据类型 - 我不想让
CsvDataProvider
知道迁移的情况 - 我不想让
CsvDataMigration
知道数据来自哪里
关于我如何做到这一点,有什么建议吗?
注意:我没有包括CsvDataMigration
类,因为我认为它在解释中没有用处,但如果需要,我会包括它。
既然不能更改GetRecords
,那么最简单的方法可能是向迁移接口询问记录类型,并使用反射调用具有运行时获得的类型的通用GetData
方法。类似于:
public void ProcessFile(string path)
{
Type recordType = _migration.InputRecordType;
var getDataMethod =
_provider.GetType()
.GetMethod("GetData")
.MakeGenericMethod(recordType);
var records = getDataMethod.Invoke(_provider, new object[] { path });
_migration.Migrate(records);
}
通常,您将定义一个非通用的替代方案,如
public interface ICsvDataProvider
{
IEnumerable GetData(string filepath, Type recordType)
IEnumerable<TRecord> GetData<TRecord>(string filepath)
where TRecord : class;
}
所以你可以称之为
public class CsvDataMigrationController
{
private string targetTypeName = ...;
public void ProcessFile(string path)
{
var recordType = Type.GetType(this.targetTypeName);
var records = _provider.GetData(path, recordType);
_migration.Migrate(records);
}
}
通过这种方式,泛型方法只是围绕非泛型方法的一点语法糖。
使用反思(如@Cameron的回答)是另一种解决方案。在这两种情况下,您都必须在运行时知道目标类型(而不是像泛型方法所要求的那样在编译时知道)。