繁体   English   中英

泛型:如何检查T的确切类型,没有T的对象

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM