методы, которые возвращают разные типы возврата - PullRequest
0 голосов
/ 23 января 2020

У меня есть методы ниже, и они возвращают разные сущности в дополнение к тому, что входные параметры, идущие к этим методам, все одинаковы, и я использую те, в которых условие

   public IQueryable<LibraryEnvironment> EnvironmentFields(string spaceFunction, string category, string source)
    {
        return _dbContext.LibraryEnvironment.Where(s => s.SpaceFunction == spaceFunction
                                                                && s.Category == category &&
                                                                 s.EnvironmentSource.Name == source);
    }

    public IQueryable<LibraryEquipment> EquipmentFileds(string spaceFunction, string category, string source)
    {
        return _dbContext.LibraryEquipment.Where(s => s.SpaceFunction == spaceFunction
                                                              && s.Category == category &&
                                                               s.EquipmentSource.Name == source);
    }

    public IQueryable<LibraryLighting> LightingFields(string spaceFunction, string category, string source)
    {
        return _dbContext.LibraryLighting.Where(s => s.SpaceFunction == spaceFunction
                                                             && s.Category == category &&
                                                              s.LightingSource.Name == source);
    }

есть другие методы, подобные и в этом роде

Я ищу способ создать общий метод generi c среди всех этих методов, но с другим типом возвращаемого значения и не смог бы его выяснить. Я использую. Net core с EF core

, если кто-нибудь предложит какие-либо идеи по этому поводу, которые будут мне очень благодарны, заранее спасибо

Ответы [ 3 ]

4 голосов
/ 23 января 2020

Вы можете использовать метод Set<T> в DbContext для общего доступа к наборам. Если вы поместите все соответствующие свойства вашей фильтрации в базу, вы можете ограничить параметр generi c этим базовым типом и по-прежнему фильтровать все ваши свойства.

Таким образом, ваши классы будут выглядеть примерно так: на ваши исходные запросы:

public class Entity
{
    public string SpaceFunction { get; set; }
    public string Category { get; set; }
}

public class LightingEquipment : Entity
{
    public LightingSource LightingSource { get; set; }
}

public class LightingSource
{
    public string Name { get; set; }
}

И ваш метод хотел бы это, используя селектор источника:

public IQueryable<T> Fields<T>(string spaceFunction, string category, string source, Func<T, string> sourceSelector) where T : Entity
{
    return _dbContext.Set<T>().Where(s => s.SpaceFunction == spaceFunction
                              && s.Category == category &&
                              sourceSelector(s) == source);
}

И вы бы назвали этот метод следующим образом:

public void Consumer()
{
    var queryable = Fields<LightingEquipment>("spaceFunction", "category", "source", x => x.LightingSource.Name);
}

Документы для Set<T>()

2 голосов
/ 23 января 2020

Если вам нужен только один метод, возможно, вы можете обойтись без Generics, как упомянул @ColinM, проверяя тип, чтобы решить, какой блок кода выполнить.
Haven ' Я проверил это, и это может быть неправильным подходом. Это немного зависит от того, где вы его используете.

public T Fields<T>(string spaceFunction, string category, string source)
{
    Type tt = typeof(T);
    if(tt == typeof(IQueryable<LibraryEnvironment>))
        return _dbContext.LibraryEnvironment.Where(s => s.SpaceFunction == spaceFunction
                                                        && s.Category == category &&
                                                          s.EnvironmentSource.Name == source);
    if (tt == typeof(IQueryable<LibraryEquipment>))
        return _dbContext.LibraryEquipment.Where(s => s.SpaceFunction == spaceFunction
                                                      && s.Category == category &&
                                                        s.EquipmentSource.Name == source);
    if (tt == typeof(IQueryable<LibraryLighting>))
        return _dbContext.LibraryLighting.Where(s => s.SpaceFunction == spaceFunction
                                                      && s.Category == category &&
                                                      s.LightingSource.Name == source);
    return default;
}

Затем вы можете вызвать метод, указав тип возвращаемого значения:

Fields<IQueryable<LibraryEnvironment>>("a", "b", "c");
Fields<IQueryable<LibraryEquipment>>("a", "b", "c");
Fields<IQueryable<LibraryLighting>>("a", "b", "c");
2 голосов
/ 23 января 2020

Я думаю, вы обнаружите, что ваш нынешний дизайн самый чистый. Ваш код не является полностью «generi c», так как они извлекаются из разных таблиц и имеют разные предложения where (например, s.EnvironmentSource.Name == source против s.LightingSource.Name == source).

Вы могли бы быть в состоянии объединить некоторые функциональности, например, обобщив доступ к таблице по типу и комбинировав часть s.Category == category фильтра, но вы будете иметь смесь отражений (или операторов switch) и дженерики, которые могут быть хуже, чем у вас сейчас.

...