答案 0 :(得分:0)
您能用这种机制描述您正在解决的问题吗?很可能有一种更清晰的方式来接近它。
修改强>
是的,代码闻起来。您已为任何类型打开了空间,除非您将其约束回单个类型,并生成运行时异常。为什么在这种情况下有一个类型参数?
答案 1 :(得分:0)
编辑:请注意,在编辑完全更改问题之前,已给出了此答案。因此,它现在指的是最初只在问题中出现的事物。我请你原谅所有“晃来晃去的指针”。 : - )
简答:
使用您发布的代码,我没有看到转换为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>
实现,这将为if
内的switch
链或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
的具体对象。看看它,如果它听起来不像你一样矫枉过正! : - )
答案 2 :(得分:0)
你可以试试这样的......
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调用。