【问题标题】:Autofac: Resolving variant types with both in and out type argumentsAutofac:使用输入和输出类型参数解析变体类型
【发布时间】:2011-11-11 12:48:52
【问题描述】:

这个问题是我上一个问题的后续问题:Autofac: Hiding multiple contravariant implementations behind one composite

我正在尝试找到 Autofac 的协变和逆变支持的边界。我注意到 Autofac 的 ContravariantRegistrationSource 仅支持带有单个泛型参数的泛型接口,该泛型参数标有 in 关键字。这似乎限制了此功能的有用性,我想知道 Autofac 是否有其他方法来扩展对协变和逆变的支持。

我必须承认,我之所以提出这个问题,并不是因为我正在从事一个真正的应用程序设计。为了教育,我故意试图找到 Autofac 的限制。

所以考虑如下接口:

public interface IConverter<in TIn, out TOut>
{
    TOut Convert(TIn value);
}

以及以下实现:

public class ObjectToStringConverter : IConverter<object, string>
{
    string IConverter<object, string>.Convert(object value)
    {
        return value.ToString();
    }
}

以及以下注册:

var builder = new ContainerBuilder();

builder.RegisterSource(new ContravariantRegistrationSource());

builder.RegisterType<ObjectToStringConverter>()
    .As<IConverter<object, string>>();

var container = builder.Build();

通过这种设计和配置,我希望能够做到这一点:

// This call succeeds because IConverter<object, string> is
// explicitly registered.
container.Resolve<IConverter<object, string>>();

// This call fails, although IConverter<string, object> is
// assignable from IConverter<object, string>.
container.Resolve<IConverter<string, object>>();

或者让我用给定的定义更抽象地说:

public class A { }
public class B : A { }
public class C : B { }

public class AToCConverter : IConverter<A, C> { ... }

以及以下注册:

builder.RegisterType<AToCConverter>()
    .As<IConverter<C, A>>();

我希望以下调用能够成功:

container.Resolve<IConverter<C, A>>();
container.Resolve<IConverter<B, B>>();
container.Resolve<IConverter<A, C>>();

我们如何使用 Autofac 做到这一点?

【问题讨论】:

    标签: c# dependency-injection ioc-container autofac covariance


    【解决方案1】:

    我认为这是我们在 Autofac 中不太可能克服的限制,但探索它很有趣。

    我们可以进行逆变'resolve',因为给定一个泛型类型参数,我们可以找到该参数可分配给的所有基本/接口类型。也就是说,给定string,我们可以搜索objectIComparable等的实现。

    反其道而行之——从一个参数类型到它的所有子类——并不是那么容易。鉴于object,我们需要一些方法来查找其他所有内容。

    可以使用容器中注册的具体组件的知识,例如扫描所有组件以寻找可能的实现并向后工作,但这对 Autofac 来说不是很好,因为在许多情况下我们依赖“拉”模型来懒惰地创建组件。

    希望这是值得深思的,有兴趣看看你的想法。

    【讨论】:

      【解决方案2】:

      您注意到ContravariantRegistrationSource 仅识别具有一个泛型参数的类型是正确的。查看the source(目前大约在第166 行),您会在那里看到该限制。看看注册源是如何提供可能的候选人的,我可以理解,取消限制将需要更多的实施复杂性。

      我会说这并不能证明您已达到 Autofac 的限制,只能证明此特定注册源的限制。我将把它作为练习留给读者以增强 ContravariantRegistrationSource 的实现,我相信 Autofac 项目非常乐意将其重新纳入核心。

      【讨论】:

      • 与1相等的检查是计算逆变参数的个数;仍然可以处理任意数量的其他(非逆变)参数。干杯!
      猜你喜欢
      • 2020-03-07
      • 2014-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-26
      • 2021-09-16
      • 1970-01-01
      • 2019-03-27
      相关资源
      最近更新 更多