有帮助吗?

解决方案

修改请注意,给出这个答案之前,这个问题是在编辑完全改变过来。正因为如此,它现在是指东西,只存在于问题的最初规定。请原谅所有的“悬摆指针”。 : - )


<强>短的答案:

通过你发布的代码,我没有看到一个替代铸造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>实现,这将节省您的内部ifswitch链或FooFactory.CreateFoo<T>块,使你的代码更容易,并摆脱了必要投(你的关心)的。

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


P.S:您可能会发现一些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容器(温莎,结构图等),以及登记,在那里实现IFoo的所有类型,然后在需要的地方调用Activator.CreateInstance时解决这些问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top