Передача общего имени класса в 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