具有逆变类型参数和Unity容器的泛型

本文关键字:泛型 Unity 类型参数 | 更新日期: 2023-09-27 18:14:59

我有一个具有逆变类型参数的接口,例如IFoo:

interface IFoo<in T> {}

现在我有三个类:

class B {}
class D : B {}
class Foo : IFoo<B> {}

如果我这样注册它们

container.RegisterType<IFoo<B>, Foo>();

…然后尝试解决IFoo<D>,它失败了,因为我没有真正注册IFoo<D>IFoo<>. 很明显。

我目前的解决方案只是迭代Registrations,从解析类型(在我的情况下是IFoo<D>)中找到RegisteredType可分配的注册,然后解析其MappedToType类型。

问题很简单:有没有更好的方法来做到这一点?如有任何建议,不胜感激。

谢谢。

编辑:

多一点上下文

我有某种映射器。

IMapper<in TSource, in TDest> : IMapper // IMapper is non-generic
{
    void Map(TSource source, TDest dest);
}

我想只注册基本映射器(其中TSourceIEnumerable<T>),并能够为实现IEnumerable<T>的每种类型解析此映射器,例如T[]:

object source = GetSource(); // runtime type is T[]
object dest = GetDest();
Type mapperType = typeof(IMapper<,>).MakeGenericType(source.GetType(), dest.GetType());
IMapper mapper = (IMapper) container.Resolve(mapperType);
mapper.Map(source, dest);

是的,我只对基于Unity/c#的方法感兴趣…

具有逆变类型参数和Unity容器的泛型

听起来好像每次都要解析同一个Mapper。如果这是正确的,并且IEnumerable<>是您的映射器需要处理的唯一接口,那么您的方法似乎有点矫枉过正。

我会尝试使用非通用IEnumerable()注册映射器,而不是IEnumerable<T> (container.RegisterType<IFoo<IEnumerable>, Foo>();)。如果我没记错的话,一个泛型IEnumerable<T>可以传递给一个非泛型IEnumerable()参数,所以你不需要担心传递的是什么类型参数。所以当你去解析映射器时,你甚至不需要检查类型,只需要解析IMapper<IEnumerable>

编译如下代码:

[TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {            
            IEnumerable<int> coll = new int[0];
            IEnumerable coll2 = coll;
         var blah = new Test<IEnumerable<int>>();
    }
}
public interface ITest<in T> where T : IEnumerable
{
}
public class Test<T> : ITest<T> where T : IEnumerable { }

如果你需要IMapper的不同实现,那就是另一回事了。在这种情况下,您必须注册每个实现。