[英]Generics: How to check the exact type of T, without object for T
如何在没有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是抽象类=如果=)
你可以写
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()
...
T _business = new T();
string businessName = _business.GetBusinessName();
return businessName;
我不知道C#语法,但是不可能这样做:
public class BusinessManager<T> where T : Business, new()
{
private T _business;
public string ShowBusinessName()
{
string businessName;
_business = new T();
return _business.GetBusinessName();
}
}
由于其他人已经对你的第一个问题给出了各种答案,我想谈谈第二个问题:设计。
1. BusinessManager
角色
BusinessManager
类在示例中的实际角色不太清楚。 由于这个类是通用的,并且它不应该关注T
的实际类型,因此它只是在Business类和程序的其余部分之间添加另一个不必要的层。
换句话说,您可以简单地使用:
Business casino = new Casino();
Response.Write(casino.GetBusinessName());
Business drugStore = new DrugStore();
Response.Write(drugStore.GetBusinessName());
将它包含在另一个泛型类中对你没有多大帮助。 另一方面,如果要为所有这些类提供一些通用功能,可以将其直接添加到抽象类中,也可以提取接口并为该接口创建扩展方法。
2.使用吸气剂的属性
第二,使用简单的getter方法时,使用属性更合适。 换句话说,你应该用Name
属性替换GetBusinessName()
方法(我也从名称中省略了“Business”,因为没有必要:
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对象。 我猜C#应该有一个等价物。 如果由于某种原因你不能使用类似的东西,你可以创建一个包含所需类型的0个元素的数组,然后检查该数组的类型。 这可能比实例化未知类型的元素便宜。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.