C# 基于类型约束的Ninject条件泛型绑定

C# 基于类型约束的Ninject条件泛型绑定,c#,.net,dependency-injection,ninject,C#,.net,Dependency Injection,Ninject,我需要在Ninject上执行一个通用的绑定,但我遇到了一些问题。这些是课程: 公共类BaseBL:IDisposable,IBaseBL 地点:班级 { .... } public类BaseLogAuditoriaBL:BaseBL、IBaseBL 地点:BaseLogAuditoriaEntity { .... } 我希望当我的tenty从BaseLogAuditoriaEntity继承时,它调用BaseLogAuditoriaBL,否则它调用BaseBL 在这种情况下,如何以通用方式配置

我需要在
Ninject
上执行一个通用的
绑定
,但我遇到了一些问题。这些是课程:

公共类BaseBL:IDisposable,IBaseBL
地点:班级
{
....
}
public类BaseLogAuditoriaBL:BaseBL、IBaseBL
地点:BaseLogAuditoriaEntity
{
....
}
我希望当我的
tenty
BaseLogAuditoriaEntity
继承时,它调用
BaseLogAuditoriaBL
,否则它调用
BaseBL

在这种情况下,如何以通用方式配置我的
绑定

如果我把它放在每个类中,它是有效的,但是我需要一个通用的解决方案来解决这个问题

例如:

kernel.Bind(typeof(IBaseBL<>)).To(typeof(BaseBL<>));
kernel.Bind(typeof(IBaseBL<Loja>)).To(typeof(BaseLogAuditoriaBL<>));
kernel.Bind(typeof(IBaseBL)).To(typeof(BaseBL));
Bind(typeof(IBaseBL)).To(typeof(BaseLogAuditoriaBL));
您可以使用
When(..)
语法创建满足您需要的条件绑定:

public static class BaseBLBindingExtensions
{
    public static IBindingInNamedWithOrOnSyntax<object> WhenEntityMatchesType<TEntityType>(
        this IBindingWhenSyntax<object> syntax)
    {
        return syntax.When(request => DoesEntityMatchType(request, typeof(TEntityType)));
    }

    private static bool DoesEntityMatchType(IRequest request, Type typeToMatch)
    {
        return typeToMatch.IsAssignableFrom(request.Service.GenericTypeArguments.Single());
    }
}
赞成者:

  • 解析速度比使用
    时(…)
    约束时快
反对:

  • 仅当包含实体的程序集在启动时已知时(应用约定时)才起作用
  • 增加启动时间
kernel.Bind(typeof(IBaseBL<>)).To(typeof(BaseBL<>));
kernel.Bind(typeof(IBaseBL<>)).To(typeof(BaseLogAuditoriaBL<>))
    .WhenEntityMatchesType<BaseLogAuditoriaEntity>();
using FluentAssertions;
using Ninject;
using Ninject.Activation;
using Ninject.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace NinjectTest.SO40310046
{
    public interface IBaseBL<TEntity>
        where TEntity : class
    { }

    public class BaseBL<TEntity> : IBaseBL<TEntity>
        where TEntity : class
    { }

    public class SimpleEntity { }

    public class BaseLogAuditoriaEntity
    { }

    public class ChildBaseLogAuditorialEntity: BaseLogAuditoriaEntity
    { }

    public class BaseLogAuditoriaBL<TEntity> : BaseBL<TEntity>, IBaseBL<TEntity>
        where TEntity: BaseLogAuditoriaEntity
    { }

    public static class BaseBLBindingExtensions
    {
        public static IBindingInNamedWithOrOnSyntax<object> WhenEntityMatchesType<TEntityType>(this IBindingWhenSyntax<object> syntax)
        {
            return syntax.When(request => DoesEntityMatchType(request, typeof(TEntityType)));
        }

        private static bool DoesEntityMatchType(IRequest request, Type typeToMatch)
        {
            return typeToMatch.IsAssignableFrom(request.Service.GenericTypeArguments.Single());
        }
    }

    public class UnitTest
    {
        [Fact]
        public void Test()
        {
            var kernel = new StandardKernel();

            kernel.Bind(typeof(IBaseBL<>)).To(typeof(BaseBL<>));
            kernel.Bind(typeof(IBaseBL<>)).To(typeof(BaseLogAuditoriaBL<>))
                .WhenEntityMatchesType<BaseLogAuditoriaEntity>();


            kernel.Get<IBaseBL<SimpleEntity>>()
                .Should().BeOfType<BaseBL<SimpleEntity>>();

            kernel.Get<IBaseBL<BaseLogAuditoriaEntity>>()
                .Should().BeOfType<BaseLogAuditoriaBL<BaseLogAuditoriaEntity>>();

            kernel.Get<IBaseBL<ChildBaseLogAuditorialEntity>>()
                .Should().BeOfType<BaseLogAuditoriaBL<ChildBaseLogAuditorialEntity>>();
        }
    }
}
kernel.Bind(typeof(IBaseBL<>)).To(typeof(BaseBL<>));
kernel.Bind(typeof(IBaseBL<BaseLogAuditoriaEntity>))
    .To(typeof(BaseLogAuditoriaBL<BaseLogAuditoriaEntity>));
kernel.Bind(typeof(IBaseBL<ChildBaseLogAuditoriaEntity>))
    .To(typeof(BaseLogAuditoriaBL<ChildBaseLogAuditoriaEntity>));