首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >codecampserver中的StaticFactory是众所周知的模式吗?

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

Stack Overflow用户
提问于 2010-04-13 01:03:19
回答 3查看 224关注 0票数 5
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-04-13 01:32:12

编辑:请注意,此答案是在问题在编辑中完全更改之前给出的。正因为如此,它现在指的是原来只存在于问题中的东西。我为所有的“摇摆不定的指针”道歉。:-)

简短回答:

使用您发布的代码,我看不出有其他方法可以转换为IFoo<T>。如果你不这样做,编译器会给出一个警告(至少在我的机器上)。

更详细的答案:

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

我假设您将像这样调用您的工厂方法:

代码语言:javascript
复制
var stringFoo = FooFactory.CreateFoo<string>();

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

现在,由于您必须在运行时显式指定类型,因此您也可以这样写:

代码语言:javascript
复制
var stringFoo = StringFoo.Create();

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

代码语言:javascript
复制
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块,使您的代码更容易,并消除强制转换(您所关心的)的必要性。

不要误会我的意思,我知道工厂方法支持多个对象类型在某些情况下很有用;但在您的例子中,它似乎带来了更多的麻烦。

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

代码语言:javascript
复制
var builder = new ContainerBuilder();
builder.RegisterType<StringFoo>().As<IFoo<string>>();

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

代码语言:javascript
复制
using (var container = builder.Build())
{
    var stringFoo = container.Resolve<IFoo<string>>();
    ...
}

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

票数 0
EN

Stack Overflow用户

发布于 2010-04-13 01:05:04

你能描述一下你用这个机制解决的问题吗?很可能有一种更清晰的方法来处理它。

编辑

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

票数 0
EN

Stack Overflow用户

发布于 2010-04-13 02:17:27

你可以试试这样的..。

代码语言:javascript
复制
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调用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2623859

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档