Autofac:使用输入和输出类型参数解析变体类型

发布于 2024-12-03 00:02:55 字数 2245 浏览 2 评论 0原文

这个问题是我上一个问题的后续问题:Autofac:隐藏多个逆变一个组合背后的实现

我试图找到 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 做到这一点?

This question is a follow up of my previous question: Autofac: Hiding multiple contravariant implementations behind one composite.

I'm trying to find the boundries of what we can do with Autofac's covariance and contravariance support. I noticed that Autofac's ContravariantRegistrationSource only supports generic interfaces with a single generic parameter that is marked with the in keyword. This seems to limit the usefulness of this feature, and I'm wondering if Autofac has other ways in extending the support of covariance and contravariance.

I must admit that I'm not asking this because of a real application design I'm working of. I'm deliberately trying to find Autofac's limits for the sake of education.

So consider the following interface:

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

And the following implementation:

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

And the following registation:

var builder = new ContainerBuilder();

builder.RegisterSource(new ContravariantRegistrationSource());

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

var container = builder.Build();

With this design and configuration, I'd expect to be able to do this:

// 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>>();

Or let me put it more abstractly, with the given definitions:

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

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

And the following registration:

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

I would expect the following calls to succeed:

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

How can we do this with Autofac?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

没有伤那来痛 2024-12-10 00:02:55

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

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

朝相反的方向走——从参数类型到所有它的子类 - 并不那么容易。给定object,我们需要某种方法来查找其他所有内容。

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

希望这是值得深思的,有兴趣看看你能想到什么。

I think this is a limitation we're unlikely to overcome in Autofac, but it is interesting to explore.

We can do contravariant 'resolve' because given a generic type argument we can find all of the base/interface types to which that argument would be assignable. That is, given string we can search for implementations for object, IComparable etc.

Going in the opposite direction - from an argument type to all of its subclasses - isn't so easy. Given object we'd need some way to look for everything else.

It may be possible to use knowledge of the concrete components registered in the container, e.g. scan all components looking for possible implementations and work backwards, but this isn't great for Autofac because we rely on a 'pull' model to lazily create components in many cases.

Hope this is food for thought, interested to see what you come up with.

情绪失控 2024-12-10 00:02:55

您正确地观察到 ContravariantRegistrationSource 仅识别具有一个泛型参数的类型。查看来源(目前大约在行166) 你会在那里看到这个限制。看看如何要求注册源提供可能的候选者,我可以理解,解除限制将需要更复杂的实施。

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

You're correct in observing that the ContravariantRegistrationSource only recognizes types with one generic parameter. Looking at the source (currently at approx. line 166) you'll see that limitation right there. Looking at how the registration source is required to provide possible candidates I can understand that lifting the limitation will require more complexity in the implementation.

I would say that this doesn't prove that you have reached Autofac's limits, only the limits of this particular registration source. I'll leave it as an exercise for the reader to enhance the ContravariantRegistrationSource implementation and I'm sure the Autofac project is more than happy to accept it back into the core.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文