Ответ 1
Вы должны сделать
public class BusinessManager<T> where T : Business, new()
...
T _business = new T();
string businessName = _business.GetBusinessName();
return businessName;
Как я могу проверить/оценить точный тип T без объекта для T. Я знаю, что мой вопрос может быть запутанным, но рассмотрим это...
public abstract class Business
{
public abstract string GetBusinessName();
}
public class Casino : Business
{
public override string GetBusinessName()
{
return "Casino Corp";
}
}
public class DrugStore : Business
{
public override string GetBusinessName()
{
return "DrugStore business";
}
}
public class BusinessManager<T> where T : Business
{
private Casino _casino;
private DrugStore _drugStore;
public string ShowBusinessName()
{
string businessName;
if (T == Casino) // Error: How can I check the type?
{
_casino = new Casino();
businessName = _casino.GetBusinessName();
}
else if (T == DrugStore) // Error: How can I check the type?
{
_drugStore = new DrugStore();
businessName = _drugStore.GetBusinessName();
}
return businessName;
}
}
Я просто хочу иметь что-то подобное на клиенте.
protected void Page_Load(object sender, EventArgs e)
{
var businessManager = new BusinessManager<Casino>();
Response.Write(businessManager.ShowBusinessName());
businessManager = new BusinessManager<DrugStore>();
Response.Write(businessManager.ShowBusinessName());
}
Обратите внимание, что я фактически не создал фактический объект для Казино и Аптеки, когда я вызываю BusinessManager, я просто передаю его как ограничение общего типа класса. Мне просто нужно точно знать, какой тип я передаю BusinessManager, чтобы узнать , что именно Тип для создания экземпляра. Спасибо...
PS: Я не хочу создавать отдельный конкретный BusinessManager для казино и аптеки..
Вы также можете прокомментировать дизайн.. спасибо..
ДОПОЛНИТЕЛЬНО: и что, если класс Casino и DrugStore - АБСТРАКТНЫЙ КЛАСС =)
Вы должны сделать
public class BusinessManager<T> where T : Business, new()
...
T _business = new T();
string businessName = _business.GetBusinessName();
return businessName;
Вы можете написать
if(typeof(T) == typeof(Casino))
но на самом деле этот тип логики является запахом кода.
Здесь один из способов:
public class BusinessManager<T> where T : Business, new() {
private readonly T business;
public BusinessManager() {
business = new T();
}
}
но лично я бы предпочел
public class BusinessManager<T> where T : Business {
private readonly T business;
public BusinessManager(T business) {
this.business = business;
}
public string GetBusinessName() {
return this.business.GetBusinessName();
}
}
Я не знаю синтаксиса С#, но это невозможно сделать:
public class BusinessManager<T> where T : Business, new()
{
private T _business;
public string ShowBusinessName()
{
string businessName;
_business = new T();
return _business.GetBusinessName();
}
}
Поскольку другие парни уже показали разные ответы на ваш первый вопрос, я хотел бы обратиться ко второму: design.
1. Роль BusinessManager
Фактическая роль класса BusinessManager
в вашем примере не слишком ясна. Поскольку этот класс является общим, и он не должен касаться фактического типа T
, то он не делает ничего, кроме добавления лишнего слоя между бизнес-классом и остальной частью программы.
Другими словами, вы можете просто использовать:
Business casino = new Casino();
Response.Write(casino.GetBusinessName());
Business drugStore = new DrugStore();
Response.Write(drugStore.GetBusinessName());
Обертка этого в другом родовом классе вам не поможет. С другой стороны, если вы хотите иметь некоторые общие функции для всех этих классов, вы можете либо добавить их непосредственно в абстрактный класс, либо извлечь интерфейс и создать методы расширения для этого интерфейса.
2. Использование свойств для геттеров
Во-вторых, использование свойства более уместно, если у вас есть простой метод getter. Другими словами, вы должны заменить метод GetBusinessName()
на свойство Name
(я также пропустил "Бизнес" из имени, потому что это необязательно:
public interface IBusiness
{
string Name { get; }
}
public abstract class Business : IBusiness
{
public abstract string Name { get; }
}
public class Casino : Business
{
public override string Name
{
get { return "Casino Corp"; }
}
}
public class DrugStore : Business
{
public override string Name
{
get { return "DrugStore business"; }
}
}
И тогда вы можете использовать его следующим образом:
IBusiness casino = new Casino();
Response.Write(casino.Name);
IBusiness drugStore = new DrugStore();
Response.Write(drugStore.Name);
Кроме того, вы можете видеть, что я ввел интерфейс IBusiness
. Причина этого - позволить вам реализовать этот интерфейс более разнообразными способами. Прямо сейчас вы попытаетесь вывести все классы из абстрактного класса Business
и попытаться извлечь как можно больше общих функций в абстрактном классе (что цель класса).
Но извлечение множества общих функций связано со стоимостью: всегда есть вероятность, что вам придётся создать класс, из которого не выводится из Business
. Если вы получаете доступ ко всем этим методам с помощью интерфейса IBusiness
, тогда другим частям вашей программы будет все равно, будет ли эта реализация получена из Business
или нет.
Так как GetBusinessName действительно относится к типу, а не к экземплярам типа, вы можете рассмотреть использование атрибута DescriptionAttribute (или собственный собственный атрибут BusinessNameAttribute) вместо переопределенного свойства и получить бизнес-имя BusinessManager из атрибута.
[Description("Casino Corp")]
public class Casino : Business
{
}
Теперь вам больше не нужно создавать бизнес, чтобы получить его имя. Чтобы получить описание, вы используете:
public string ShowBusinessName()
{
var attribute = Attribute.GetCustomAttribute(typeof(T), typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attribute == null)
return "Unknown business";
return attribute.Description;
}
Вы можете сделать что-то вроде этого:
if (typeof(T) == typeof(SomeType))
{
// Same
}
определите класс BusinessManager
как ниже:
public class BusinessManager<T> where T : Business
{
Business biz;
public BusinessManager()
{
biz = new T();
}
public string ShowBusinessName()
{
return biz.GetBusinessName();
}
}
и используйте его ниже:
var businessManager = new BusinessManager<Casino>();
Response.Write(businessManager.ShowBusinessName());
var anotherBusinessManager = new BusinessManager<DrugStore>();
Response.Write(businessManager.ShowBusinessName());
Способ использования вами потеряет инкапсуляцию
В VB.net вы можете использовать псевдофункцию GetType для параметра общего типа, чтобы получить объект Type отражения. Я бы предположил, что С# должен иметь эквивалент. Если по какой-либо причине вы не можете использовать что-то подобное, вы можете создать массив из 0 элементов нужного типа, а затем проверить тип этого массива. Это, вероятно, будет дешевле, чем создание экземпляра неизвестного типа.