在非泛型类中创建泛型

时间:2017-01-27 21:14:31

标签: c# generics factory factory-pattern

首先,我一直在努力争取这个问题的标题,所以如果您认为自己有更好的想法,请编辑它。

这似乎是我一次又一次遇到的问题,并最终做了一些臭臭来规避。一般形式似乎是我有一个非泛型类,用于获取某个实例(即工厂),但需要做出关于实例应该具有什么类型的决定。我认为下面的示例说明了我的目标,但您注意到它没有编译,因为在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
}

1 个答案:

答案 0 :(得分:1)

泛型的主要目的是提供编译时类型的安全性。让#39;让FooBarFactory在运行时确定if (number1 > number2) { if (number1 > number3) largest = number1; else largest = number3; } else { if (number2 > number3) largest = number2; else largest = number3; } if (number1 < number2) { if (number1 < number3) smallest = number1; else smallest = number3; } else { if (number2 < number3) smallest = number2; else smallest = number3; } 应该用于Generator<T>&#34;的类型是没有意义的。

  

我的目的是强制工厂返回AbstractThing。

这是由返回类型为T的工厂方法强制执行的。

  

你会在这里推荐什么?工厂应该只为AbstractThing的每个子类型设置一个方法吗?

GetThing方法,即工厂方法,应该根据您的某些逻辑返回AbstractThing,即非通用工厂本身决定是返回Foo还是Bar对象。泛型并不适用于此。

  

或者也许应该在工厂中没有Generator的实例,而是在每个案例块中新建相应的Generator?

您不一定需要任何生成器类。如果需要,您可以实现决定是否应在工厂方法中直接创建AbstractThingFoo的逻辑。工厂将N个参数作为输入,并根据工厂中抽象出来的一些逻辑返回Bar类型的具体实现。

希望这是有道理的。

相关问题