Я пытаюсь создать универсальный класс, который обновляет экземпляр родового типа. Как показано ниже:
public class HomepageCarousel<T> : List<T>
where T: IHomepageCarouselItem, new()
{
private List<T> GetInitialCarouselData()
{
List<T> carouselItems = new List<T>();
if (jewellerHomepages != null)
{
foreach (PageData pageData in jewellerHomepages)
{
T item = new T(pageData); // this line wont compile
carouselItems.Add(item);
}
}
return carouselItems;
}
}
Но я получаю следующую ошибку:
не может предоставлять аргументы при создании экземпляра переменной тип
Я нашел следующий связанный с ним вопрос, который очень близок к тому, что мне нужно: Передача аргументов в С# generic new() шаблонного типа
Однако я не могу использовать Джареда, который предложил ответить, поскольку я вызов метода в классе Generic, а не за пределами это, поэтому я не могу указать конкретный класс.
Есть ли способ обойти это?
Я пробовал следующее по другому вопросу, но это не работает, поскольку я не знаю конкретного типа T указывать. Поскольку он вызывается изнутри общего класса, а не снаружи:
public class HomepageCarousel<T> : List<T>
where T: IHomepageCarouselItem, new()
{
private List<T> LoadCarouselItems()
{
if (IsCarouselConfigued)
{
return GetConfiguredCarouselData();
}
// ****** I don't know the concrete class for the following line,
// so how can it be instansiated correctly?
return GetInitialCarouselData(l => new T(l));
}
private List<T> GetInitialCarouselData(Func<PageData, T> del)
{
List<T> carouselItems = new List<T>();
if (jewellerHomepages != null)
{
foreach (PageData pageData in jewellerHomepages)
{
T item = del(pageData);
carouselItems.Add(item);
}
}
return carouselItems;
}
}
******** ИЗМЕНИТЬ: ДОБАВЛЕННЫЕ ВОЗМОЖНЫЕ РЕШЕНИЯ **
Итак, я протестировал 2 возможных решения:
В первую очередь, как описано ниже Jon Skeet. Эта определенно работает, но означает наличие неясной лямбды в конструктор. Мне это не очень удобно, так как это означает пользователи должны знать правильную лямбду, которая ожидается. В конце концов, они могут пройти лямбду, которая не тип, но делает что-то совершенно неожиданное
Во-вторых, я пошел по маршруту метода Factory; Я добавил метод Create к общему интерфейсу:
IJewellerHomepageCarouselItem Create(PageData pageData);
Затем была реализована реализация в каждом классе Concrete:
public IJewellerHomepageCarouselItem Create(PageData pageData)
{
return new JewellerHomepageCarouselItem(pageData, null);
}
И использовал двухэтапный синтаксис инициализации:
T carouselItem = new T();
T homepageMgmtCarouselItem = (T) carouselItem.Create(jewellerPage);
Хотелось бы услышать некоторые отзывы о достоинствах каждого из этих подходов.