通过通用接口/抽象类实现使.NET Core DI自动解析类 [英] Make .NET Core DI auto resolve class by generic interface / abstract class implementation

查看:288
本文介绍了通过通用接口/抽象类实现使.NET Core DI自动解析类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

.NET Core中是否可以注册通用接口,并使其解析与特定实现匹配的类。

Is there a way in .NET Core to register a generic interface, and make it resolve a class that matches a certain implementation.

例如,我拥有以下接口:

For example, I have the following interface:

public interface IMapper<TFrom, TTo>
{
}

我也有一个抽象类:

public abstract class Mapper<TFrom, TTo> : IMapper<TFrom, TTo>
{
    protected Mapper()
    {
        // some generic stuff
    }

    public abstract TTo Map(TFrom);
}

然后,我可以像这样创建实现:

I can then create an implementation like so:

public class UserMapper : Mapper<Domain.User, Entity.User>
{
    public override Entity.User Map(Domain.User from)
    {
        // do mapping
    }
}

有没有办法使用默认的.NET Core DI来注册 IMapper<,> ,并让它自动解析该类?

Is there a way, using the default .NET Core DI to register IMapper<,>, and let it auto resolve the class?

因此,例如,如果我在代码中的某处这样做:

So if I for example would do this somewhere in code:

class SomeClass
{
    public SomeClass(IMapper<Domain.User, Entity.User> mapper) {}
}

它以某种方式知道应该解析类 UserMapper< Domain.User,Entity .User>

That it somehow knows that it should resolve the class UserMapper<Domain.User, Entity.User>?

原因是手动注册每个特定于实现的映射器有点冗长。因此,我希望 Microsoft.DependencyInjection 足够聪明,可以以某种方式自动解决其实现。

The reason is that it's a little verbose to manually register each and every mapper, specific to an implementation. So I'm hoping Microsoft.DependencyInjection is smart enough to automatically resolve its implementation somehow.

推荐答案

当前设计的唯一方法是使用反射:

The only way with your current design is to use Reflection:

Assembly assembly = typeof(UserMapper).Assembly;

foreach (var type in assembly.GetTypes()
    .Where(t => t.IsClass && !t.IsAbstract))
{
    foreach (var i in type.GetInterfaces())
    {
        if (i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMapper<,>))
        {
            // NOTE: Due to a limitation of Microsoft.DependencyInjection we cannot 
            // register an open generic interface type without also having an open generic 
            // implementation type. So, we convert to a closed generic interface 
            // type to register.
            var interfaceType = typeof(IMapper<,>).MakeGenericType(i.GetGenericArguments());
            services.AddTransient(interfaceType, type);
        }
    }
}




注意:您可以通过在 IServiceCollection 上创建扩展方法并使 AddTransient AddSingleton 等。

NOTE: You could make it simpler by creating an extension method on IServiceCollection with the various overloads for AddTransient, AddSingleton, etc.

如果您更改设计,请使用非抽象的泛型作为您的实现类型:

If you change the design use a non-abstract generic as your implementation type:

public class Mapper<TFrom, TTo> : IMapper<TFrom, TTo>
{
    //...
}

然后可以像这样简单地注册:

Then you can simply register like this:

services.AddTransient(typeof(IMapper<,>), typeof(Mapper<,>));

这篇关于通过通用接口/抽象类实现使.NET Core DI自动解析类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆