簡體   English   中英

使用泛型轉換為基類

[英]Casting to a base class using generics

我似乎在理解C#中的泛型時遇到了一些麻煩。

基本上,我有一個名為ConfigWorker的基類和許多子類,它們都應使用從BaseConfig派生的自己的配置類。

我要使用的ConfigWorker類應該在運行時動態確定,並以類的名稱為參數。

我可以實例化給定其名稱的子類,但是無論我嘗試什么,我都無法將轉換強制轉換為明智的基類。

這是我的代碼:

namespace DocumentHandler
{

    public class BaseConfig
    {
    }

    public class ConfigWorker<T> where T : BaseConfig
    {
        public virtual void Work(T options)
        {

        }

    }

    public class Worker1 : ConfigWorker<Worker1.Config>
    {
        public class Config : BaseConfig
        {
            public string test = "";
        }

        public override void Work(Config options)
        {
            //do something
        }
    }

    public class Worker2 : ConfigWorker<Worker2.Config>
    {
        public class Config : BaseConfig
        {
            public string test = "";
        }

        public override void Work(Config options)
        {
            //do something else
        }
    }

    public class Test
    {
        public static BaseConfig config; 

        public static void test()
        {
            (Activator
                .CreateInstance(Type.GetType("DocumentHandler.Worker2")) 
                as ConfigWorker<BaseConfig>)
            .Work(config);
        }
    }
}

關鍵是

(Activator
    .CreateInstance(Type.GetType("DocumentHandler.Worker2")) 
    as ConfigWorker<BaseConfig>)
.Work(config);

強制轉換為ConfigWorker<BaseConfig>返回null,因為無法執行強制轉換。

由於缺少類型參數,因此無法簡單地ConfigWorkerConfigWorker

我還能嘗試什么嗎? CreateInstance顯然只是返回一個對象,我需要CreateInstance該對象才能調用Work方法

任何幫助表示贊賞。

Worker2的實例不是ConfigWorker ConfigWorker<BaseConfig> 這是ConfigWorker<Worker2.Config> 這是兩種完全不同的類型。 泛型類是不變的。 只有接口和委托可以是協變或反變的。

在您的示例中, ConfigWorkerT甚至是反變的,這意味着您將T用作方法的輸入參數的類型。 因此,您嘗試的實際上是危險的。

想象一下您的行將工作:您將獲得類型為ConfigWorker<BaseConfig>的變量,因此您可以依賴於此實例,該實例具有一個方法Work() ,該方法將BaseConfig (或BaseConfig派生的東西)作為參數。 所以沒有什么可以阻止您像這樣稱呼它

worker.Work(new Worker1.Config());

編譯正常。 但請稍等! 您的Worker2不是說workerworker Worker2嗎? Worker2實例只能處理Worker2.Config參數!
這樣您就完全失去了類型安全性(好吧,如果允許的話,您會這樣做)。

您的班級設計中存在缺陷。

工廠模式具有很好的解決方案,這似乎是一個好問題。 這是一個簡化的解決方案

 namespace DocumentHandler
{

    public interface IBaseConfig
    {
    }

    public class ConfiManager : IBaseConfig
{

}

    public abstract class WorkerFactory
    {

        private readonly IBaseConfig _config;

        protected WorkerFactory(IBaseConfig config)
        {
            this._config = config;
        }

        public virtual void Work()
        {

        }





    }

    public class Worker1 : WorkerFactory
{
    private readonly IBaseConfig _config;

    public Worker1(IBaseConfig config):base(config)
    {
        _config = config;
    }

            public string test = "";


        public override void Work()
        {
            //do something
        }
    }

    public class Worker2 : WorkerFactory
{
    private readonly IBaseConfig _config;

            public string test = "";

            public Worker2(IBaseConfig config):base(config)
            {
                this._config = config;
            }


            public override void Work()
        {
            Console.WriteLine("Hello world");
        }
    }

    public class Test
    {
        public static IBaseConfig config = new ConfiManager();

        public static void test()
        {
            WorkerFactory worker =
                (Worker2) Activator.CreateInstance(Type.GetType("DocumentHandler.Worker2"), config);

            worker.Work();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM