繁体   English   中英

codecampserver中的StaticFactory是一个众所周知的模式吗?

[英]Is the StaticFactory in codecampserver a well known pattern?

更新:这是codecampserver中的StaticFactory是众所周知的模式的副本吗?

你能用这种机制描述你正在解决的问题吗? 很可能有一种更清晰的方法来接近它。

编辑

是的,代码闻起来。 您已为任何类型打开了空间,除非您将其约束回单个类型,并生成运行时异常。 为什么在这种情况下有一个类型参数?

编辑:请注意,在编辑完全更改问题之前,已给出了此答案。 因此,它现在指的是最初只在问题中出现的事物。 我请你原谅所有“晃来晃去的指针”。 :-)


简短回答:

使用您发布的代码,我没有看到转换为IFoo<T>的替代方法。 如果不这样做,编译器将发出警告(至少在我的机器上)。

更详细的答案:

你的代码真的必须这样吗? 更具体地说,你首先需要有问题的演员吗?

我假设您将或多或少地调用您的工厂方法:

var stringFoo = FooFactory.CreateFoo<string>();

您必须显式提供模板参数(在本例中为string ),因为它不能从任何方法参数派生(在这种情况下,因为实际上根本没有)。 显然,工厂方法将返回IFoo<string>

现在,既然你必须在运行时明确指定类型,你也可以写:

var stringFoo = StringFoo.Create();

因此在StringFoo有一个像这样的工厂方法,它无条件地做了显而易见的事情:

public class StringFoo : IFoo<string>
{
    ...

    public static StringFoo Create()  // or alternatively, return an IFoo<string>
    {
        return new StringFoo();
    }
}

通过将此模式应用于其他IFoo<T>实现,这将在FooFactory.CreateFoo<T>保存if链或switch块,使代码更容易,并且摆脱了FooFactory.CreateFoo<T> switch的必要性(您关注的是)。

不要误会我的意思,我知道,工厂方法支持多个对象类型某些情况下非常有用; 但在你的情况下,它似乎造成了更多麻烦而不是它的价值。


PS:你可能会发现一些IoC容器的一个方面很有趣。 它们通常需要配置,这包括一个为抽象接口注册具体类型(即实现类)的过程; 例如(这里使用Autofac ):

var builder = new ContainerBuilder();
builder.RegisterType<StringFoo>().As<IFoo<string>>();

然后,您可以请求抽象类型的对象实例:

using (var container = builder.Build())
{
    var stringFoo = container.Resolve<IFoo<string>>();
    ...
}

Resolve方法是有趣的部分。 您为它提供了一个抽象类型,并使用已注册的类型,它将返回StringFoo类型的具体对象。 看看它,如果它听起来不像你一样矫枉过正! :-)

你可以试试这样的......

public static class FooFactory
{
    private static readonly Dictionary<Type, Type> FooTypesLookup;

    static FooFactory()
    {
        FooTypesLookup = (from type in typeof(FooFactory).Assembly.GetExportedTypes()
                          let fooInterface =
                            type.GetInterfaces().FirstOrDefault(
                                x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IFoo<>))
                          where fooInterface != null
                          let firstTypeArgument = fooInterface.GetGenericArguments().First()
                          select new { Type = type, TypeArgument = firstTypeArgument })
            .ToDictionary(x => x.TypeArgument, x => x.Type);
    }

    public static IFoo<T> CreateFoo<T>()
    {
        var genericArgumentType = typeof(T);
        Type closedFooType;
        return FooTypesLookup.TryGetValue(genericArgumentType, out closedFooType)
                ? (IFoo<T>) Activator.CreateInstance(closedFooType)
                : null;
    }
}

或者更好的是,介绍您最喜欢的IoC容器(Windsor,结构图等)并注册所有在那里实现IFoo的类型,然后在需要时解决它们来代替Activator.CreateInstance调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM