简体   繁体   中英

methods that are returning different return types

I have below methods and they are returning different entities in addition to that the input parameters going to these methods all are same and I am using those ones in where condition

   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);
    }

there are other methods similar to this kind as well

I am looking for a way to create the common generic method among all these methods but with a different return type and could not be able to figure it out the way. I am using.Net core with EF core

if anyone suggest any ideas on this that would be very grateful to me, thanks in advance

You can use the Set<T> method on DbContext to generically access sets. If you put all the relevant properties your filtering on into a base you can then constrain the generic parameter to that base type and still filter on all your properties.

So your classes would look something like this based on your original queries:

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; }
}

And your method would like this, using a source selector:

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);
}

And you would call this method like this:

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

Docs for Set<T>()

I think you're going to find that your current design is the cleanest. Your code isn't completely "generic" since they pull from different tables and have different where clauses (eg s.EnvironmentSource.Name == source vs s.LightingSource.Name == source ).

You might be able to combine some of the functionality by, for example, genericising the table access by type and combining the s.Category == category part of the filter, but you're going to have a mix of reflection (or switch statements) and generics that could be uglier than what you have now.

If you're only looking to have one method, perhaps you can get away with Generics, as @ColinM mentioned while checking the type to decide which block of code to execute.
Haven't tested it, and it could be the wrong approach. It depends a bit on where you're using it.

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;
}

You can then call the method specifying the return type:

Fields<IQueryable<LibraryEnvironment>>("a", "b", "c");
Fields<IQueryable<LibraryEquipment>>("a", "b", "c");
Fields<IQueryable<LibraryLighting>>("a", "b", "c");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM