简体   繁体   中英

How do we create c# method to accept different types of parameter

I am new to asp.net and creating a MVC project using entities framework. Mostly it work as I expected but have an issue where I need to pass parameters to a method which could be of different types. I need this because I dont want to write same method in each class which send same results. Here is my setup

public class BaseQuery : IOSSQuery
{
    private Entities dbcontext;

    public BaseQuery() : this(new Entities())
    {
    }
    public BaseQuery(Entities context)
    {
        this.dbcontext = context;
    }
    public List<SimpleItem> GetAllItemsFromQuery<T>( T table,Int32 skip)
    {
        List<SimpleItem> SimpleItemList = new List<SimpleItem>();
        SimpleItemList = table.Where(p => p.IsActive == true).OrderBy(p => p.Name).Select(p => new SimpleItem { id = p.Id, Name = p.Name, IsActive = p.IsActive }).Skip(skip).Take(30).Distinct().ToList();
        return SimpleItemList;
    }
    public virtual List<SimpleItem> GetAllItems(Int32 skip)
    {
        List<SimpleItem> SimpleItemList = new List<SimpleItem>();
        return SimpleItemList;
    }
}

Then I have a query class,

public class ColorQuery : BaseQuery
{
    public override List<SimpleItem> GetAllItems(Int32 skip)
    {
        return GetAllItemsFromQuery( dbcontext.tbl_color, skip)
    }
}

Here is the interface

public interface IOSSQuery : IDisposable
{
    List<SimpleItem> GetAllItems(Int32 skip);
}

I would like to call the method from my controller as following

public JsonResult Color(String range)
{
   ColorQuery query = new ColorQuery();
   List<string> ranges = range.Split(',').ToList<string>();
   var SimplePage = getAllItems(query, Convert.ToInt32(ranges[0]));
   return Json(SimplePage, JsonRequestBehavior.AllowGet);
}

public PagedData<SimpleItem> getAllItems( IOSSQuery queryObject,  int range )
{
   var SimplePage = new PagedData<SimpleItem>();
   SimplePage.total = queryObject.TotalItems();
   SimplePage.data = queryObject.GetAllItems(range);
   return SimplePage;
}

This code throw error at this line in BaseQuery class

public List<SimpleItem> GetAllItemsFromQuery<T>( T table,Int32 skip)

Error   CS1061  'T' does not contain a definition for 'Where' and no extension method 'Where' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?)

Not sure how do I pass different types in the method. I tried solution from Method to accept different types without luck. Can anybody shed lights on this. Thanks for your time.

Edits: This is how it setup in my entities

public DbSet<tbl_Category> tbl_Category { get; set; }
public DbSet<tbl_color> tbl_color { get; set; }

EDIT 2:

I have multiple tables with different columns. My idea is to use generic method from "BaseQuery" for all tables which returns same result still want to use "ColorQuery" or say "CategroyQuery" class for different query if I need.

It seems like you T table is should be limited to IEnumerable<T> because you use it like an IEnumerable<T> :

SimpleItemList = table.Where(p => p.IsActive == true).OrderBy(p => p.Name).Select(p => new SimpleItem { id = p.Id, Name = p.Name, IsActive = p.IsActive }).Skip(skip).Take(30).Distinct().ToList();

Try to declare it using where (using System.Linq ):

public List<SimpleItem> GetAllItemsFromQuery<T, U>(T table,Int32 skip) where T : System.Collections.IEnumerable<U>

Or simply:

public List<SimpleItem> GetAllItemsFromQuery<T>(IEnumerable<T> table,Int32 skip)

why don't you try with an IQueryable parameter instead of a generic Type Parameter?

public List<SimpleItem> GetAllItemsFromQuery(IQueryable table,Int32 skip)
    {
        List<SimpleItem> SimpleItemList = new List<SimpleItem>();
        SimpleItemList = table.Where(p => p.IsActive == true).OrderBy(p => p.Name).Select(p => new SimpleItem { id = p.Id, Name = p.Name, IsActive = p.IsActive }).Skip(skip).Take(30).Distinct().ToList();
        return SimpleItemList;
    }

When you make the GetAllItemsFromQuery method generic (using T as a parameter type) the compiler no longer knows what type of object it is receiving in parameter table - so when you invoke members like IsActive or extension methods like Where , the compiler cannot bind them to concrete implementations; in fact, it can't tell if the object you're passing in even /has/ those members. You can give the compiler more information about the types it can expect using where clauses on the method declaration:

public List<SimpleItem> GetAllItemsFromQuery<T>( T table,Int32 skip)
    where T: IEnumerable<IEntity>
{
    List<SimpleItem> SimpleItemList = new List<SimpleItem>();
    SimpleItemList = table.Where(p => p.IsActive == true).OrderBy(p => p.Name).Select(p => new SimpleItem { id = p.Id, Name = p.Name, IsActive = p.IsActive }).Skip(skip).Take(30).Distinct().ToList();
    return SimpleItemList;
}

Assuming that all your entity types implement IEntity , which would be an interface including Id , Name , IsActive et cetera.

It would be easier to give you a specific answer if we could see the code for the Entities type, but in terms of what you're trying to do the where clause is the way to go.

You can use function name overload . It's OK.

Sammer,

the problem in your code is that you are using a generic Type Parameter, as @FacticiusVir said, the compiler can't know which kind of Type is, but at the same time you want this type to have an Id property, a Name property and IsActive property.

So you can do two things:

  1. Make the method GetAllItemsFromQuery more specific, something like that:

        public List GetAllItemsFromQuery(IEnumerable table, Int32 skip)
        {
            List SimpleItemList = new List();
            SimpleItemList = table.Where(p => p.IsActive).OrderBy(p => p.Name).Select(p => new SimpleItem { id = p.Id, Name = p.Name, IsActive = p.IsActive }).Skip(skip).Take(30).Distinct().ToList();
            return SimpleItemList;
        }
  1. Make it generic with a restriction and create a base class for your entities with the three properties mentioned before:

     public class tbl_color: BaseEntity { } public class BaseEntity { public bool IsActive { get; set; } public string Name { get; set; } public int Id { get; set; } } public List<SimpleItem> GetAllItemsFromQuery<T>(IEnumerable<T> table, Int32 skip) where T : BaseEntity { List<SimpleItem> SimpleItemList = new List<SimpleItem>(); SimpleItemList = table.Where(p => p.IsActive).OrderBy(p => p.Name).Select(p => new SimpleItem { id = p.Id, Name = p.Name, IsActive = p.IsActive }).Skip(skip).Take(30).Distinct().ToList(); return SimpleItemList; } 

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