簡體   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