带有派生通用类的FactoryPattern

问题描述 投票:0回答:1

这是一个简短的片段,我已经隐藏了无关紧要的细节。目标是使我的工厂使用我的泛型设计类型。在文章的结尾,我有两个观察结果。

接口

public interface IWorker<T> where T : IWorkload 
{
    T CraftWorkload(string plainWorkload);
    Task DoWork(T workload);
}

IWorkload

public interface IWorkload
{
    // some properties
}

基类

internal abstract class Worker<T> : IWorker<T> where T : IWorkload
{
    public T CraftWorkload(string workAsJsonString)
    {
        return JsonConvert.DeserializeObject<T>(workAsJsonString, new JsonSerializerSettings
        {
            MissingMemberHandling = MissingMemberHandling.Error
        });
    }

    public abstract Task DoWork(T workload);
}

另一个派生基类

internal abstract class RestWorker<T> : Worker<T> where T : IWorkload
{ 
  // this is a worker that interact with http requests
}

混凝土工人

internal class WorkerA: RestWorker<WorkerA_Workload>
{
    public override Task DoWork(WorkerA_Workload workload)
    {
    }
}

internal abstract class WorkerB: Worker<WorkerB_Workload>
{
    public override Task DoWork(WorkerB_Workload workload)
    {
    }
}

WorkersFactory

MessageType是用类型标识工作者的枚举

internal interface IWorkerFactory
{
    IWorker<IWorkload> GetWorker(MessageType type);
}

internal class WorkerFactory : IWorkerFactory
{
    public IWorker<IWorkload> GetWorker(MessageType type)
    {
        switch (type)
        {
            case MessageType.WorkerA:
                return new WorkerA() as IWorker<IWorkload>;
            case MessageType.WorkerB:
                return new WorkerB() as IWorker<IWorkload>;
           .
           .
           .
           .
           .
            default:
                throw new ArgumentException("The type must be a type that maps to an available worker");
        }
    }
}

两个观察:

  1. 如果我将Factory更改为不带隐式强制转换为IWorker<IWorkload>就返回,则会感到困惑
  2. 如果我强制转换(如代码所示),则返回null

我的继承有意义吗?

c# generics factory-pattern derived-class base-class
1个回答
0
投票

您的IWorker<T>接口表示一个既可以产生T类型的对象,又可以[消耗类型T的对象的工作程序(因为它同时使用T作为方法的参数和方法的返回类型)。这意味着IWorker<IWorkload>是能够产生IWorkload类型的对象的对象,WorkerAWorkerB可以做到,因为它们产生的WorkerA_WorkloadWorkerB_Workload对象是IWorkload对象。但这也意味着IWorker<IWorkload>需要能够接受*任何IWorkload并对其进行处理。 WorkerAWorkerB都不能这样做。它们只能分别接受WorkerA_WorkloadWorkerB_Workload输入,但是要实现IWorker<IWorkload>的接口,它们将必须能够接受< [任何其他类型的工作负载

如果您的工作人员实际上可以接受any IWorkload,并且实际上他们不需要接受特定类型的工作负载,那么您需要调整代码以基本上删除受IWorkload约束的所有通用类型,而改为只需在所有这些地方使用非通用IWorkload类型。 (您还需要使IWorker<T>相对于T协变。)

如果您的工作人员不能实际上接受任何IWorkload,并且需要特定类型的工作负载,那么您不能将所有工作人员都视为IWorker<IWorkload>,则需要始终将他们视为IWorker<T>,其中T是他们可以接受的实际特定工作负载类型。

© www.soinside.com 2019 - 2024. All rights reserved.