【问题标题】:How to remove repetitive Ninject Bindings?如何删除重复的 Ninject 绑定?
【发布时间】:2020-02-04 12:44:24
【问题描述】:

我当前的 GeneralBindings : Ninject 模块

public class GeneralBindings : NinjectModule
    {
        public override void Load()
        {
            // Requires Ninject.Extensions.Conventions
            // This binds all interfaces to concretes of the same name eg IClass -> Class.
            Kernel.Bind(x => x.FromAssembliesMatching("Company.Project.Scm*")
                .SelectAllClasses()
                .Excluding(typeof(AffectedCables),
                    typeof(ApplicationConfigurations),
                    typeof(ApplicationErrors),
                    typeof(ApplicationLogEvents),
                    typeof(AppUsers),
                    typeof(AppUsersContract),
                    typeof(Areas)

                    // etc..

                )
                .BindAllInterfaces());

然后

            Bind<IAffectedCables>().To<AffectedCables>()
                .InSingletonScope()
                .WithConstructorArgument("url", @"api/AffectedCables");

            Bind<IApplicationErrors>().To<ApplicationErrors>()
                .InSingletonScope()
                .WithConstructorArgument("url", @"api/AppErrors");

            Bind<IApplicationConfigurations>().To<ApplicationConfigurations>()
                .InSingletonScope()
                .WithConstructorArgument("url", @"api/AppConfigurations");

            Bind<IApplicationLogEvents>().To<ApplicationLogEvents>()
                .InSingletonScope()
                .WithConstructorArgument("url", @"api/AppEventLogs");

            Bind<IAppUsers>().To<AppUsers>()
                .InSingletonScope()
                .WithConstructorArgument("url", @"api/AppUsers");

            Bind<IAppUsersContract>().To<AppUsersContract>()
                .InSingletonScope()
                .WithConstructorArgument("url", @"api/AppUserContract");

            Bind<IAreas>().To<Areas>()
                .InSingletonScope()
                .WithConstructorArgument("url", @"api/Areas");

            // Etc...
...

谁能建议如何更好地做到这一点?我确信有人可以创建一行代码来保存我目前必须执行的复制和粘贴。

【问题讨论】:

    标签: ninject ninject-extensions


    【解决方案1】:

    盲拍,未经测试,但我会尝试使用属性

    public class AutoBindWithRouteAttribute : Attribute
    {
        public string Route { get; }
    
        public AutoBindWithRouteAttribute(string route = null)
        {
            Route = route;
        }
    }
    

    然后

        // to bind your first block of code for classes not featuring the attribute
        kernel.Bind(
            x => x.FromAssembliesMatching("").SelectAllClasses()
                .Where(t => !t.GetCustomAttributes(typeof(AutoBindWithRouteAttribute), false).Any())
               .BindAllInterfaces());
    
        // to bind your second block of code for classes featuring the attribute
        kernel.Bind(
            x => x.FromAssembliesMatching("").SelectAllClasses()
                .Where(t => t.GetCustomAttributes(typeof(AutoBindWithRouteAttribute), false).Any())
                .BindWith(new BindingGenerator()));
    

    BindingGenerator 在哪里:

    public class BindingGenerator : IBindingGenerator
    {
        public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
        {
            var att =
                type.GetCustomAttributes(typeof(AutoBindWithRouteAttribute), false).FirstOrDefault() as
                    AutoBindWithRouteAttribute;
            if (att == null) yield break;
    
            yield return (IBindingWhenInNamedWithOrOnSyntax<object>)bindingRoot
                .Bind(type.GetInterfaces().First())
                .To(type)
                .InSingletonScope()
                .WithConstructorArgument("url", att.Route ?? $"api/{type.Name}");
        }
    }
    

    然后使用:

    [AutoBindWithRoute()]
    public class AffectedCables : IAffectedCables
    
    [AutoBindWithRoute(@"api/AppErrors")]
    public class ApplicationErrors : IApplicationErrors
    

    【讨论】:

      【解决方案2】:

      遵循 jbl 的优秀建议解决方案,因为我有

       public class AffectedCables : DataAccessBase<AffectedCableEntity>, IAffectedCables
          {
      ...
          }
      

      BindingGenerator 绑定了DataAccessBase,所以我做了一个小改动,改用相关接口:

      public class BindingGenerator : IBindingGenerator
              {
                  public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type,IBindingRoot bindingRoot)
                  {
                      var att =
                          type.GetCustomAttributes(typeof(AutoBindWithRouteAttribute), false).FirstOrDefault() as
                              AutoBindWithRouteAttribute;
                      if (att == null) yield break;
      
                      yield return (IBindingWhenInNamedWithOrOnSyntax<object>) bindingRoot
                          .Bind(type.GetInterfaces().First(x => x.Name == $"I{type.Name}"))
                          .To(type)
                          .InSingletonScope()
                          .WithConstructorArgument("url", att.Route ?? $@"api/{type.Name}");
                  }
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-01-07
        • 1970-01-01
        • 2017-07-24
        • 1970-01-01
        • 2012-02-09
        • 2017-01-30
        • 1970-01-01
        相关资源
        最近更新 更多