如何在没有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时,我实际上没有为Casino和Drugstore创建实际对象,我只是将其作为类的泛型类型约束传递。我只需要确切知道我通过哪个类型的BusinessManager来了解要实例化的Type究竟是什么。感谢...
PS:我不想为Casino和Drugstore创建单独的特定BusinessManager。
您也可以对设计发表评论..谢谢..
附加:如果类Casino和DrugStore是抽象类,那该怎么办?)
答案 0 :(得分:12)
你可以写
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();
}
}
答案 1 :(得分:9)
你应该做
public class BusinessManager<T> where T : Business, new()
...
T _business = new T();
string businessName = _business.GetBusinessName();
return businessName;
答案 2 :(得分:2)
我不知道C#语法,但是不可能这样做:
public class BusinessManager<T> where T : Business, new()
{
private T _business;
public string ShowBusinessName()
{
string businessName;
_business = new T();
return _business.GetBusinessName();
}
}
答案 3 :(得分:2)
由于其他人已经对你的第一个问题给出了各种答案,我想谈谈第二个问题:设计。
<强> 1。 BusinessManager
示例中BusinessManager
类的实际角色不太清楚。由于这个类是通用的,并且它不应该关注T
的实际类型,因此它只是在Business类和程序的其余部分之间添加另一个不必要的层。
换句话说,你可以简单地使用:
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
。
答案 4 :(得分:2)
由于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;
}
答案 5 :(得分:1)
您可以这样做:
if (typeof(T) == typeof(SomeType))
{
// Same
}
答案 6 :(得分:1)
将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());
你使用你的方式将失去封装
答案 7 :(得分:1)
在VB.net中,您可以在泛型类型参数上使用GetType伪函数来获取反射Type对象。我猜C#应该有一个等价物。如果由于某种原因你不能使用类似的东西,你可以创建一个包含所需类型的0个元素的数组,然后检查该数组的类型。这可能比实例化未知类型的元素便宜。