在 Non-Generic Class 中创建泛型

Creating Generics in Non-Generic Class

首先,我一直在纠结如何给这个问题起标题,所以如果您认为自己有更好的主意,请编辑它。

这似乎是我 运行 时不时遇到的一个问题,最后我做了一些令人讨厌的事情来规避。一般形式似乎是我有一个 non-generic class 用于获取某物的实例(即工厂),但需要就实例应具有的类型做出决定。我认为下面的示例说明了我的目的,但您会注意到它无法编译,因为在 FooBarFactory 中我不能将 AbstractThing 用于 T 作为摘要' 在这种情况下允许。那么,如何让 FooBarFactory 在 运行 时确定 Generator<T> 应该为 T 使用哪种类型?

public class FooBarFactory
{
    private Generator<AbstractThing> _generator;

    public AbstractThing GetThing(string data, ThingType type)
    {
        switch (type)
        {
            case ThingType.Foo:
                _generator = new FooGenerator();
                break;

            case ThingType.Bar:
                _generator = new BarGenerator();
                break;

            case ThingType.None:
                return null;

            default:
                throw new ArgumentOutOfRangeException(nameof(type), type, null);
        }

        return _generator.Generate(data);
    }
}

public abstract class Generator<T> where T : AbstractThing, new()
{
    protected T GeneratedThing = new T();

    protected abstract void MapDataToThing(string data);

    public T Generate(string data)
    {
        MapDataToThing(data);
        return GeneratedThing;
    }
}

public class FooGenerator : Generator<Foo>
{
    protected override void MapDataToThing(string data)
    {
        GeneratedThing.AbstractProp = ParseAbstract(data);
        GeneratedThing.FooProp = ParseFoo(data);
    }

    private static string ParseAbstract(string data)
    {
        throw new NotImplementedException();
    }

    private static string ParseFoo(string data)
    {
        throw new NotImplementedException();
    }
}

public class BarGenerator : Generator<Bar>
{
    protected override void MapDataToThing(string data)
    {
        GeneratedThing.AbstractProp = "Base property in Bar";
        GeneratedThing.BarProp = data.Substring(4, 3);
    }
}

public abstract class AbstractThing
{
    public string AbstractProp { get; set; }
}

public class Foo : AbstractThing
{
    public string FooProp { get; set; }
}

public class Bar : AbstractThing
{
    public string BarProp { get; set; }
}

public enum ThingType
{
    None = 0,
    Foo = 1,
    Bar = 2
}

泛型的主要目的是提供compile-time类型安全。 "let the FooBarFactory determine, at runtime, which type the Generator<T> should use for T".

没有意义

My intention was to enforce that the factory returns an AbstractThing.

这是由 return 类型 AbstractThing 的工厂方法强制执行的。

What would you recommend here? Should the factory simply have a method for each subtype of AbstractThing?

GetThing 方法,即工厂方法,应该简单地 return 一个 AbstractThing 基于你的一些逻辑,即它是 non-generic 工厂本身决定是否 return 一个 Foo 或一个 Bar 对象。泛型在这里并不适用。

Or maybe should there be no instance of Generator in the factory, instead newing up the appropriate Generator within each case block?

您不一定需要任何发电机 class。如果需要,您可以实现决定是否应直接在工厂方法本身中创建 FooBar 的逻辑。工厂将 N 个参数作为输入,return 基于工厂中抽象的某些逻辑的 AbstractThing 类型的具体实现。

希望这是有道理的。