发布于 2010-04-13 01:32:12
编辑:请注意,此答案是在问题在编辑中完全更改之前给出的。正因为如此,它现在指的是原来只存在于问题中的东西。我为所有的“摇摆不定的指针”道歉。:-)
简短回答:
使用您发布的代码,我看不出有其他方法可以转换为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块,使您的代码更容易,并消除强制转换(您所关心的)的必要性。
不要误会我的意思,我知道工厂方法支持多个对象类型在某些情况下很有用;但在您的例子中,它似乎带来了更多的麻烦。
附言:您可能会发现一些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类型的具体对象。看看它,如果你不觉得它听起来太过了!:-)
发布于 2010-04-13 01:05:04
你能描述一下你用这个机制解决的问题吗?很可能有一种更清晰的方法来处理它。
编辑
是的,代码很难闻。您已经为任何类型留出了空间,除非您将其约束回单个类型,并生成运行时异常。在这种情况下,为什么要有类型参数?
发布于 2010-04-13 02:17:27
你可以试试这样的..。
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调用。
https://stackoverflow.com/questions/2623859
复制相似问题