2013-07-02 68 views
1

我有下面的情况下实现我的接口的类需要多个仿制药,但只使用其中的一个在其实施的接口(另一个是关闭的)的....注册局部打开泛型与Autofac

public interface ITest<T, TU> 
{     
} 

public class Test<T, TU> : ITest<Guid, T> 
{ 
} 

我曾尝试注册这个作为

builder.RegisterGeneric(typeof (Test<,>)).AsImplementedInterfaces(); 

builder.RegisterGeneric(typeof (Test<,>)).As(typeof (ITest<,>)); 

但当余吨RY解决的

container.Resolve<ITest<Guid, string>>(); 

我得到

所请求的服务“ITest`2 [的System.Guid,mscorlib程序, 版本= 4.0.0.0,文化=中立, 公钥= b77a5c561934e089] ,[System.String,mscorlib, Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]' 尚未注册。为避免此异常,请注册 组件以提供服务,使用 IsRegistered()检查服务注册,或使用ResolveOptional()方法解析 可选依赖项。

我猜它假设泛型在实现和接口中是同一类型的吗?有什么建议么?

感谢

+0

它是开源的,所以你可以看看在通用的解决方案代码:https://code.google.com/p/autofac/source/browse/Core/Source/Autofac/Features/OpenGenerics/OpenGenericServiceBinder.cs –

+0

您的'测试'是否需要它的第二个泛型参数?因为如果你有这样的'public class Test :ITest '然后注册'builder.RegisterGeneric(typeof(Test <>))。AsImplementedInterfaces();'工作正常。 – nemesv

+0

不幸的是,我确实需要两个通用参数 – Levitron

回答

2

问题是由泛型参数TUTest<T, TU>引起的。请理解,TUITest<TU, T>中定义的TU参数无关,但这是一个完全不同的参数。为了使这个更加明显,你应该重命名参数,例如:因为通用参数是不同的,并且不映射到ITest<TU, T>抽象的一般说法

public class Test<T, X> : ITest<Guid, T> 
{ 
} 

,Autofac是无法从请求推断X关闭版本ITest<TU, T>。问问自己:如果我要求ITest<Guid, string>X应该是什么。这将解析为Test<string, X>,但X仍未知。

由于Autofac无法推断出X,因此永远无法使用Test<T, X>,请求将失败。

由于Test<T, X>永远无法得到解决,但不幸的是,Autofac没有在通话过程中抛出一个异常RegisterGeneric,因为它应该能够找出Test<T, X>将永远不会得到解决。

所以真正的问题是,当ITest<Guid, T>得到解决时,你想X是什么? Autofac不允许使用部分泛型类型定义,但C#编译器都不是,所以这通常不是问题。最简单的方法来“填补”那X说法是由Test<T, X>得出:

// Part of your Composition Root 
internal class FloatTest<T> : Test<T, float> 
{ 
} 

这个类可以没有问题地注册:

builder.RegisterGeneric(typeof(FloatTest<>)) 
    .As(typeof(ITest<,>)) 
+0

当退后一步并查看问题时,这是有道理的。谢谢。 – Levitron