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

tuk*_*aef 6 .net c# generics dependency-injection unity-container

我有一个带逆变型参数的接口,比如说IFoo:

interface IFoo<in T> {}
Run Code Online (Sandbox Code Playgroud)

现在我有三个班:

class B {}

class D : B {}

class Foo : IFoo<B> {}
Run Code Online (Sandbox Code Playgroud)

如果我这样注册他们

container.RegisterType<IFoo<B>, Foo>();
Run Code Online (Sandbox Code Playgroud)

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

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

问题很简单:有更好的方法吗?任何意见,将不胜感激.

谢谢.

编辑:

多一点背景.

我有一些映射器.

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

我想只登记基础映射器(其中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);
Run Code Online (Sandbox Code Playgroud)

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

Sco*_*rry 0

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

我会尝试使用 non-generic 来注册映射器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 { }
Run Code Online (Sandbox Code Playgroud)

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