繁体   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