理解由于继承和接口实现而变得复杂的泛型方法

本文关键字:实现 接口 变得复杂 泛型方法 于继承 继承 | 更新日期: 2023-09-27 18:27:26

我有一个基类DataSource实现和一个通用接口IDataSource

class DataSource
{
DataSource (DateTime dt){}
DataSource (IData data) {}
DataSource (IData data, DateTime dt){}
}
public interface IDataSource<TValue> where TValue:IData
{
        TValue DataEntry{get;set;}
        string RootFolder { get; }
}

我的派生类(没有任何成员)

 BestSource : DataSource, IDataSource<BestData> {}
 ConsistentSource :DataSource, IDataSource<ConsistentData> {}
 BackupSource :  DataSource, IDataSource<BackupData> {}

现在我正试图在IData上创建一个扩展方法,它将创建适当的类并从中获取数据…

public static IEnumerable<TValue> GetAllData<TValue, TSource>(this IData entity) 
        where TSource : DataSource, IDataSource<TValue>
        where TValue : IData
    {
        string folderName = $"_{entity.Name}";
        //One way I kinda got it work (well atleast not show compiletime errors)                                         
       //was to create a method in base class DataSource that used 
       //if-else cascade to return an appropriate instance...
       TSource dataSource =  (TSource) new DataSource(entity).GetSource(t);
       //but that's obviously a bad way of doing it. 
        //I want to avoid using reflection for no other reason than to just learn more about inheritence and working around/with it. 
        //I need an instance of it so I can access the json files at the rootfolder directory and also to deserilize the json.

        var returnData = Directory.EnumerateFiles(dataSource.RootFolder+folderName)
                       .Select(x => 
                          JsonConvert.DeserializeObject<TValue>(File.ReadAllText(x)));
        return returnData;
    }

前面工作的一个简单解决方案是只向它传递DataSource派生类的一个实例。但后来我试着让它从它实现的接口的类型参数中找出派生类。这是我第一次尝试使用泛型。

编辑:好的,所以我能够通过在所有DataSource子类中创建一个无参数构造函数来实现我想要的。我真的很想避免这种情况,因为这是以通过添加setter使我的属性可变为代价的。呃,我只是从构造函数内部设置它们,效果很好。我将继续寻找一些方法来回到这一点,同时仍然保留扩展方法的功能。

理解由于继承和接口实现而变得复杂的泛型方法

(非通用版本)您可以尝试表达式:

public static IEnumerable<TValue> GetAllData<TValue>(this TValue entity, Func<DataSource<TValue>> func)
    where TValue : IData
{
    var obj = func();
    // Get some data from obj, will be of type BestSource in this example
    return new List<TValue>() { obj.DataEntry };
}

代码中的某个位置:

BestData data = new BestData();
var receiver = data.GetAllData(() => new BestSource(data));

此外,我确实将DataSource定义为:

public class DataSource<TValue> : IDataSource<TValue> where TValue : IData

最佳来源:

public class BestSource : DataSource<BestData>

同样为了编写更少的代码,您可以为每种数据类型定义扩展方法GetAllData:

public static IEnumerable<BestData> GetAllData(this BestData entity)
{
    return entity.GetAllData(() => new BestSource(entity));
}

代码中的某个位置:

var receiver2 = data.GetAllData();