我需要在binding
上执行通用Ninject
,但我遇到了一些问题。这些是类:
public class BaseBL<TEntity> : IDisposable, IBaseBL<TEntity>
where TEntity : class
{
....
}
public class BaseLogAuditoriaBL<TEntity> : BaseBL<TEntity>, IBaseBL<TEntity>
where TEntity : BaseLogAuditoriaEntity
{
....
}
我希望当我的TEntity
继承BaseLogAuditoriaEntity
后,它会调用BaseLogAuditoriaBL
,否则会调用BaseBL
在这种情况下,我如何以通用的方式配置我的bindings
?
如果我把它放在每个班级,它都有用,但是我需要一个针对这个问题的通用解决方案。
示例:
kernel.Bind(typeof(IBaseBL<>)).To(typeof(BaseBL<>));
kernel.Bind(typeof(IBaseBL<Loja>)).To(typeof(BaseLogAuditoriaBL<>));
答案 0 :(得分:1)
您可以使用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>();
完整示例包括单元测试(使用XUnit和FluentAssertions):
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>>();
}
}
}
考虑到您的BaseLogAuditoriaBL
已经定义了类型约束,它可能是使用基于约定的绑定的可行替代方法(例如使用Ninject.Extensions.Conventions创建,它会扫描从BaseBL
继承的类型,检查类型约束,然后扫描遵守约束的所有类型,然后为这些绑定创建特定的,非条件的绑定。
生成的绑定应该类似于:
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>));
临:
When(...)
约束缺点: