2015-12-19 9 views
0

У меня есть базовый класс 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. Но потом я попытался понять, как я могу просто вычислить производный класс из параметра param интерфейса Interface, который он реализует. Это мой первый раз, пытаясь использовать дженерики.

Редактирование: Хорошо, поэтому я смог заставить его делать то, что я хотел, создав безразмерный конструктор во всех подклассах DataSource. Я действительно хотел избежать этого, потому что это произошло за счет того, что мои свойства изменялись, добавляя сеттер. EArlier я просто устанавливал их изнутри конструктора, и это сработало хорошо. Я продолжу искать способ вернуться к этому, сохраняя при этом функциональность метода расширения.

+0

Это выглядит как C#. Вы должны применить соответствующий языковой тег. – chrylis

+0

Не могли бы вы разместить все соответствующие коды, включая членов, и убедиться, что они скомпилированы? Прямо сейчас с вашим кодом сложно работать, и поэтому вопрос трудно ответить. – Enigmativity

ответ

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 as:

public class BestSource : DataSource<BestData> 

также писать меньше кода, можно определить метод расширения GetAllData для каждого типа данных:

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

Где-то в коде:

var receiver2 = data.GetAllData(); 
Смежные вопросы