理解通用方法和继承和接口实现的复杂性

时间:2015-12-19 03:40:33

标签: c# generics inheritance interface

我有一个基类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使我的属性变为可变为代价的。 EArlier我只是从构造函数中设置它们并且运行良好。我会继续寻找一些方法来回到这一点,同时仍然保持扩展方法的功能。

1 个答案:

答案 0 :(得分:0)

(不是那么通用的版本)您可以尝试表达式:

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

和BestSource:

public class BestSource : DataSource<BestData>

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

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

代码中的某处:

var receiver2 = data.GetAllData();