将带有通用接口的类添加到DI中

发布于 2025-02-05 20:34:02 字数 422 浏览 1 评论 0原文

如何将Imyinterface的每个实现注册到DI容器中?

而不是必须手动注册实现通用接口的每个类,我希望反思在启动时处理此操作。

public interface IMyInterface<T> { }

public class Foo : IMyInterface<Bar> { }

public class Baz : IMyInterface<A> { }

如何注册foobaz作为services.addtransient&lt; imyinterface&lt; bar&gt;,foo&gt;()使用反射?

how do I register each implementation of IMyInterface<T> to the DI container?

Instead of having to manually register each class that implements a generic interface I want reflection to take care of this on startup.

public interface IMyInterface<T> { }

public class Foo : IMyInterface<Bar> { }

public class Baz : IMyInterface<A> { }

How do I register Foo and Baz as services.AddTransient<IMyInterface<Bar>, Foo>() using reflection?

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

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

发布评论

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

评论(1

生生漫 2025-02-12 20:34:02

自动注册您的类型分为三个步骤:

  1. 从类型系统中请求类型
  2. 注册循环的类型
  3. 过滤您要通过列表

,并可以通过assembly进行注册。 API,通常是通过调用assembly.getTypes()或 assembly.getExportedTypes()(查看方法最适合您的文档)。但是首先,您需要访问汇编实例或实例。可以使用appDomain.currentdomain.getAssemblies()来完成此操作需求,例如,您可以通过调用typeof(foo)来获得特定类型的组件.sembly

。以下代码:

var types =
    from assembly in AppDomain.CurrentDomain.GetAssemblies()
    from type in assembly.GetTypes()
    select type;

下一步,您要过滤不实现imyinterface&lt; t&gt;的类型。这是最棘手的部分。由于以下内容将使您启动:

var registrations =
    from type in types
    where !type.IsAbstract
    where !type.IsGenericTypeDefinition
    let services =
        from iface in type.GetInterfaces()
        where iface.IsGenericType
        where iface.GetGenericTypeDefinition() == typeof(IMyInterface<>)
        select iface
    from service in services
    select new { service, type };

此代码:

  • 滤除所有抽象类型(接口和抽象类),因为它们无法注册
  • 过滤器,例如bar&lt&lt; t&gt;,因为它们通常需要特别注意和注册
  • 每个返回的接口在注册集合中产生一个项目。如果类型不实现iMyinterface&lt; t&gt;,则它将不会成为registrations集合的一部分,因此未注册(请参见下文)。如果类型多次实现iMyinterface&lt; t&gt;,它会为该接口的每个闭合版本都有一个注册(根据您的需求,这非常方便)。

现在,您有一份注册列表。剩下的任务是这些服务到实施映射的实际注册,这实际上是简单的部分:

foreach (var reg in registrations)
{
    services.AddTransient(reg.service, reg.type);
}

etvoilà。那里有它。您的所有非传播实现imyinterface&lt; t&gt;均由其封闭的imyinterface&lt; t&gt;注册。

Auto-Registering your types is done in three steps:

  1. Request types from the type system
  2. Filtering the types you want to register
  3. Loop through the list and register them

Requesting types from the type system can be done through the Assembly API, typically by calling Assembly.GetTypes() or Assembly.GetExportedTypes() (look at the documentation which method suits you best). But first you need to access the Assembly instance or instances. This can be done using AppDomain.CurrentDomain.GetAssemblies() to get all currently loaded assemblies (warning: this might not be all assemblies your application needs, or you can get the assembly of a specific type, for instance by calling typeof(Foo).Assembly. This is useful if you know that all types live in the same assembly.

This leads to the following code:

var types =
    from assembly in AppDomain.CurrentDomain.GetAssemblies()
    from type in assembly.GetTypes()
    select type;

Next, you want to filter out the types that do not implement IMyInterface<T>. This is the most tricky part, because Reflection and generic types can be a PITA. However, a filter such as the following will get you started:

var registrations =
    from type in types
    where !type.IsAbstract
    where !type.IsGenericTypeDefinition
    let services =
        from iface in type.GetInterfaces()
        where iface.IsGenericType
        where iface.GetGenericTypeDefinition() == typeof(IMyInterface<>)
        select iface
    from service in services
    select new { service, type };

This code:

  • filters out all abstract types (interfaces and abstract classes) as they can't be registered
  • filters out all generic type definitions, such as Bar<T>, because they typically require special attention and registration.
  • Gets all the interfaces of the type that implement a closed version of IMyInterface<T>.
  • Each returned interface results in a item in the registrations collection. If a type doesn't implement IMyInterface<T>, it will not be part of the registrations collection and, therefore, not registered (see below). In case a type implements IMyInterface<T> multiple times, it gets a registration for each closed version of that interface (which can be very handy, depending on your needs).

Now you have a list of registrations to make. The remaining task is the actual registration of these service-to-implementation mappings, which is actually the easy part:

foreach (var reg in registrations)
{
    services.AddTransient(reg.service, reg.type);
}

Et voilà. There you have it. All your non-generic implementations of IMyInterface<T> are registered by their closed IMyInterface<T>.

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