Предаване на общо име на клас в dbcontext

Код на контекстния файл на моите обекти:

public partial class MyDbContext : DbContext
{
    //dbset 1
    public DbSet<Customer> Customers { get; set; }

    //dbset 2
    public DbSet<Order> Orders { get; set; }
}

Class Shipments има метод GetCustomerName

public class Shipments
{
    public string GetName(object caller, System.Data.Entity.DbSet objectContext)
    {
        //This one passes.

        IQueryable<Customer> myCustomer = from p in objectContext
                                          select p where p.Id=1; //get customer name

        //This one fails
        IQueryable<caller.GetType()> myCustomer = from p in objectContext
                                                  select p where p.Id=1; //get customer name
    }
}

Въпрос: Бих искал да премахна твърдото кодиране на клас Customer там, вместо това да извикам този метод, като предам името на класа като параметър?

Как мога да приложа това? В този случай caller.GetType().Name не работи за мен.

GetName(Order, mydbContext);
GetName(Customer, mydbContext);

И двете трябва да работят с един и същ код (опитвайки се да го направя общ, не съм сигурен как да го направя общ). Всяка помощ ще бъде страхотна. Благодаря.


person Sharpeye500    schedule 18.11.2014    source източник
comment
Ще ви трябва най-малко базов тип, който има Id и Name свойства. Дори тогава ще ви е необходим превключвател или генерични средства, за да определите кое свойство от вашия контекст да поискате.   -  person D Stanley    schedule 18.11.2014


Отговори (2)


Като толкова много хора, включително и аз в началото, вие не виждате разликата между тип данни и екземпляр на класа Type. Типът данни е нещо, което е известно по време на компилиране. Когато извикате GetType, това, което получавате обратно, е обект, чийто тип данни е Type. Той съдържа информация за тип данни, но сам по себе си не е тип данни.

Това, което трябва да направите, е също да направите своя GetName метод общ:

public string GetName<T>(T caller, System.Data.Entity.DbSet objectContext)
{
    IQueryable<T> myEntity = from p in objectContext
                             select p where p.Id=1; //get customer name
}

За да може да направи това обаче, компилаторът трябва да знае, че типът T всъщност има свойство Id. Това означава, че T трябва да бъде ограничено да бъде конкретен базов клас или интерфейс, който декларира свойство Id. В случай на автоматично генерирани EF класове, интерфейсът е единствената ви опция.

Все още има други проблеми с вашия код, но това покрива това, за което всъщност питате.

person jmcilhinney    schedule 18.11.2014
comment
Бих казал, че има разлика между общи параметри на типа и параметри на метода. - person jwize; 18.11.2014
comment
@jwize, и ще бъдеш прав, но не мисля, че намекнах друго, така че не съм съвсем сигурен какво се опитваш да кажеш. - person jmcilhinney; 18.11.2014
comment
Този коментар имаше за цел просто да даде светлина на параметъра тип дума, който хората могат да търсят онлайн. Няма нищо лошо в отговора ти. - person jwize; 18.11.2014

Не виждам смисъл от предаване на аргумент object само за да получа неговия тип. Можете да използвате генерични лекарства за това:

public string GetName<T>(DbSet objectContext) where T : BaseEntity {
    IQueryable<T> myCustomer = from p in objectContext
                               select p where p.Id = 1;
    //Get the name
    //Return the name
}

Моля, обърнете внимание, че добавих ограничение за T за разширяване от BaseEntity.

След това всички ваши обекти трябва да се разширят от този абстрактен клас (който трябва да съдържа свойството Id и Name за получаване на името).

Тогава ще можете да извлечете името не само на Customer обекти, но дори и на Order обекти:

string customerName = GetName<Customer>(context);
string orderName = GetName<Order>(context);

Ако само вашият Customer обект има свойството Name, тогава изобщо не използвайте генерични, по-добре е да дефинирате типа изрично:

public string GetName(context) {
    IQueryable<Customer> customer = from p in context
                                    select p where p.Id = 1;
    //Get the name
    //Return the name
}
person Matias Cicero    schedule 18.11.2014