Одна вещь, которая возможно ясна, это то, что ваш дизайн несколько ошибочен. Переключение типа - не лучшая вещь в универсальном методе, который побеждает его цель. Но не ясно, какова цель ваших занятий.
Некоторые предположения:
1) Просмотр ваших парных классов AskItem
и AskTankTruckAggregate<T>
и т. Д. Я не думаю, что последний должен быть универсальным классом, это очень специфический класс, тесно связанный с AskItem
. Я бы изменил его как
public static class AbstractAggregateFactory
{
public static AbstractAggregate<T> GetAggregateClient<T>() where T : ListItem
{
//use reflection to find the type that inherits AbstractAggregate<T>
//instantiate the type
//cast to AbstractAggregate<T> and return
}
}
public class AskTankTruckAggregate : AbstractAggregate<AskItem>
{
//not implemented yet
}
public class TankTruckBlogAggregate : AbstractAggregate<BlogItem>
{
//not implemented yet
}
public class ResourcesAggregate : AbstractAggregate<ResourceItem>
{
//not implemented yet
}
Назовите это как:
AbstractAggregateFactory.GetAggregateClient<AskItem>(); //etc
2) Другой способ: делегировать задание по созданию совокупности вашим ListItems.
public abstract class ListItem //or interface
{
protected abstract object Create();
}
public class AskItem : ListItem { //implement to return AskTankTruckAggregate
}
public class BlogItem : ListItem { //implement to return TankTruckBlogAggregate
}
public class ResourceItem : ListItem { //implement to return ResourcesAggregate
}
public static class AbstractAggregateFactory
{
public static AbstractAggregate<T> GetAggregateClient<T>() where T : ListItem, new()
{
return (AbstractAggregate<T>)new T().Create();
}
}
public class AskTankTruckAggregate : AbstractAggregate<AskItem>
{
//not implemented yet
}
public class TankTruckBlogAggregate : AbstractAggregate<BlogItem>
{
//not implemented yet
}
public class ResourcesAggregate : AbstractAggregate<ResourceItem>
{
//not implemented yet
}
Назовите это как:
AbstractAggregateFactory.GetAggregateClient<AskItem>(); //etc
3) Или то же самое, но сделайте его более строго набранным с использованием обобщений:
public abstract class ListItem<T> where T : ListItem<T> //or interface
{
protected abstract AbstractAggregate<T> Create();
}
public class AskItem : ListItem<AskItem> { //implement to return AskTankTruckAggregate
}
public class BlogItem : ListItem<BlogItem> { //implement to return TankTruckBlogAggregate
}
public class ResourceItem : ListItem<ResourceItem> { //implement to return ResourcesAggregate
}
public static class AbstractAggregateFactory
{
public static AbstractAggregate<T> GetAggregateClient<T>() where T : ListItem, new()
{
return new T().Create();
}
}
public class AskTankTruckAggregate : AbstractAggregate<AskItem>
{
//not implemented yet
}
public class TankTruckBlogAggregate : AbstractAggregate<BlogItem>
{
//not implemented yet
}
public class ResourcesAggregate : AbstractAggregate<ResourceItem>
{
//not implemented yet
}
Назовите это как:
AbstractAggregateFactory.GetAggregateClient<AskItem>(); //etc
4) Наконец, можно ли сделать тип возвращаемого значения менее универсальным? Включает случай переключения, мне не нравится.
public enum AggregateTypes { TankTruckBlog, AskTankTruck, Resources }
public static class AbstractAggregateFactory
{
public static AbstractAggregate GetAggregateClient(AggregateTypes type)
{
switch (type)
{
case AggregateTypes.AskTankTruck:
return new AskTankTruckAggregate<AskItem>();
case AggregateTypes.TankTruckBlog:
return new TankTruckBlogAggregate<BlogItem>();
case AggregateTypes.Resources:
return new ResourcesAggregate<ResourceItem>();
default:
throw new AggregateDoesNotExistException();
}
}
}
public abstract class AbstractAggregate
{
}
public abstract class AbstractAggregate<T> : AbstractAggregate
{
}
//or change the definition to AskTankTruckAggregate : AbstractAggregate<AskItem>
public class AskTankTruckAggregate<T> : AbstractAggregate<T>
{
//not implemented yet
}
//or change the definition to TankTruckBlogAggregate : AbstractAggregate<BlogItem>
public class TankTruckBlogAggregate<T> : AbstractAggregate<T>
{
//not implemented yet
}
//or change the definition to ResourcesAggregate : AbstractAggregate<ResourceItem>
public class ResourcesAggregate<T> : AbstractAggregate<T>
{
//not implemented yet
}
Назовите это как:
AbstractAggregateFactory.GetAggregateClient(AggregateTypes.AskTankTruck); //etc
Имо, этот подход хуже, чем подход отражения. В будущем легко забыть проверить перечисление.
Из всех, 3-й выглядит лучше всего на мой взгляд, но опять же, не зная цели вашего дизайна, его очень сложно предсказать. Несколько предложений:
Название вашей фабрики звучит лучше, чем AggregateFactory
. «Аннотация» в нем делает больше о реализации.
Если вам требуется enum для обозначения типа, не делайте его вложенным. Вложенные публичные типы сложнее назвать. Выньте статический класс обтекания (как в моем пятом подходе).
Переименуйте ваш базовый класс в Aggregate<T>
или AggregateBase<T>
. Опять же «абстрактный» в нем делает больше о реализации, совершенно ненужно.