Как я могу применить общий дополнительный метод к нескольким несвязанным типам в стороннем SDK?

Если вы объясните, какой заказ клиента вы хотите и хотите ли вы указывать полную цену заказа или цену каждого товара в этом заказе, мы можем указать более конкретно. Я должен был сделать некоторые предположения (см. Комментарии):

select
      c.Company
    , o.ShipDate as this_is_max_ship_date_of_customer 
    , o.OrderID --Added OrderID so you know what the price is associated with
    , sum(oi.price) this_is_sum_of_prices_of_the_order
                --if you want the price of a particular item, you can add ItemID beneath OrderID and also group by it
from dbo.Customers c
join dbo.Orders o
    on c.CustomerID = o.CustomerID
join dbo.OrderItems oi
    on o.OrderID = oi.OrderID
where o.Deleted = 0
    and o.ShipDate in (select max(inner_o.ShipDate) from dbo.Orders inner_o
                       where inner_o.Company = c.Company
                       group by inner_o.Company)
                       --This subquery points to the outer reference - a useful trick
                       -- it means only the most recent ShipDate for the customer is shown
    and o.OrderId in (select max(inner_o2.OrderId) from dbo.Orders inner_o2
                       where inner_o2.Company = c.Company
                         and inner_o2.ShipDate = o.ShipDate
                       group by inner_o2.Company)
                       --This subquery is doing the same thing, but for your OrderId
                       --Unfortunately you don't specify enough in your question, so
                       --  I have to assume you only want their most recent order
                       --To prevent an ShipDate that is not of the OrderId you care about,
                       --  I had to add the second where clause here
group by
    c.Company,
    o.ShipDate,
    o.OrderId
9
задан balexandre 5 February 2009 в 14:47
поделиться

4 ответа

Как насчет того, чтобы писать два дополнительных метода:

public static void AddPhoneNumber(this Contact contact, PhoneType type);

и

public static void AddPhoneNumber(this Person person, PhoneType type);

Инструмент для очистки взглядов мне.

Если существует некоторый общий код между этими двумя, извлеките это в отдельный метод.

12
ответ дан 4 December 2019 в 10:05
поделиться

Сделать Contact и Person реализуйте единый интерфейс - говорят IContactWithPhoneNumbers - и затем запишите дополнительный метод "для этого интерфейса".

public interface IContactWithPhoneNumbers {}
public class Contact : IContactWithPhoneNumbers {}
public class Person : IContactWithPhoneNumbers {}
public static void AddPhoneNumber(this IContactWithPhoneNumbers obj) {}
7
ответ дан 4 December 2019 в 10:05
поделиться

Чтение комментариев (объекты от SDK и не доступны для редактирования). Я, вероятно, сделал бы что-то вроде этого:

public class Util
{
    //common util method
    public static void AddPhoneNumber(object obj, string phoneNumber)
    {
         if(obj is Contact)
             ((Contact)contact).Phones.Add(phoneNumber);
         else if(obj is Person)
             ((Person)contact).Phones.Add(phoneNumber);
    }

    //extension method for Person
    public static void AddPhoneNumber(this Person p, string phoneNumber)
    {
        AddPhoneNumber((object)p, phoneNumber);
    }

    //extension method for Contact
    public static void AddPhoneNumber(this Contact c, string phoneNumber)
    {
        AddPhoneNumber((object)c, phoneNumber);
    }
}

Я действительно думаю лучшая практика, хотя то, когда Вы имеете контроль над основными объектами, должно было бы реализовать единый интерфейс.

2
ответ дан 4 December 2019 в 10:05
поделиться

Вы можете сделать свой метод расширения универсальным, например:

public static void AddPhoneNumberToContact<T>(
    this T contact,
    PhoneType type,
    String number
)
{
    PhoneRow pr = PhoneRow.CreateNew();
    pr.SetDefaults();
    pr.PtypeIdx = type;
    pr.PhoneNumber = number;
    ((T)contact).Phones.Add(pr);
    pr = null;
}

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

Если он жалуется на невозможность разрешить метод Phones для типа T, вы можете:

Передать некоторый делегат функции , который принимает тип T, ничего не возвращает и выполняет действие ((T) contact) .Phones.Add (pr); .

Или вы можете создать интерфейс, подобный следующему:

public interface IPhoneable
{
    IList<Phone> Phones();
}

Затем, когда у вас есть этот интерфейс, вы можете добавить следующее к своему универсальному методу расширения:

public static void AddPhoneNumberToContact<T>(
    this T contact,
    PhoneType type,
    String number
) where T : IPhoneable {...}

Здесь T по-прежнему является универсальным типом, но теперь ваш метод AddPhoneNumberToContact требует, чтобы в любом случае T - это,он наследуется от интерфейса IPhoneable, который вы только что определили для использования метода Phones ().

См. также Метод расширения C # для общих коллекций .

0
ответ дан 4 December 2019 в 10:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: