2013-02-12 2 views
2

Я ищу хороший способ включить настройки внутри моего webapp (asp mvc). Я натолкнулся на действительно приятную реализацию в NopCommerce. NopCommerce сохраняет значения в таблице базы данных с именем и значением. Название происходит от имени класса и свойств (например, customersettings.settingname1)Взаимодействие с дженериками и недвижимостью в Ninject

Точный способ NopCommerce работы с настройками можно найти в этом вопросе: Understanding how Nop Commerce settings are loaded from the database

NopCommerce использует Autofac в рамках DI привязать Settings к ConfigurationProvider следующим образом (как я прав).

return RegistrationBuilder 
       .ForDelegate((c, p) => c.Resolve<IConfigurationProvider<TSettings>>().Settings) 
       .InstancePerHttpRequest() 
       .CreateRegistration(); 

В соответствующих классах, теперь вы можете использовать ClientSettings в качестве параметра, и он автоматически заполняется данными из базы данных.

Мне очень нравится эта реализация, потому что она очень гибкая. Однако проблема заключается в том, что я использую Ninject. Я попробовал несколько вещей, чтобы получить правильные привязки, но не могу найти правильную реализацию. Кто-нибудь есть идея, как заставить это работать?

EDIT:

Я нашел способ связать ClientSettings непосредственно:

kernel.Bind<ClientSettings>() 
     .ToMethod(ctx => ctx.Kernel.Get<IConfigurationProvider<ClientSettings>>().Settings) 
     .InRequestScope(); 

Но есть способ для достижения этой цели?

kernel.Bind<ISettings>() 
     .ToMethod(ctx => ctx.Kernel.Get<IConfigurationProvider<ISettings>>().Settings) 
     .InRequestScope(); 

EDIT 2

Я думаю, что я близко, но все же столкнуться с некоторыми проблемами. Я создаю специальный генератор связи:

public class SettingsBindGenerator : IBindingGenerator 
{ 
    static readonly MethodInfo BuildMethod = typeof(SettingsBindGenerator).GetMethod(
     "BuildRegistration", 
     BindingFlags.Static | BindingFlags.NonPublic);  

    public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot) 
    { 
     var obj = typeof (object).IsAssignableFrom(type); 
     if (type != null && typeof(ISettings).IsAssignableFrom(type)) 
     { 
      var buildMethod = BuildMethod.MakeGenericMethod(type); 
      var methodResult = buildMethod.Invoke(null, new object[]{bindingRoot}); 
      var castedResult = methodResult as IBindingWhenInNamedWithOrOnSyntax<object>; 
      yield return castedResult; 
     } 
    } 


    static IBindingWhenInNamedWithOrOnSyntax<TSettings> BuildRegistration<TSettings>(IBindingRoot bindingRoot) where TSettings : ISettings, new() 
    { 
     return bindingRoot.Bind<TSettings>().ToMethod(
      ctx => ctx.Kernel.Get<IConfigurationProvider<TSettings>>().Settings); 
    } 
} 

Это работает на 99%. Однако по какой-то причине buildMethod.Invoke возвращает BindingConfigurationBuilder, а не IBindingWhenInNamedWithOrOnSyntax. Поэтому castedResult всегда имеет значение NULL. Кто-нибудь понял, как это исправить?

ПОСЛЕДНИЙ EDIT

Я не знаю, почему, но вдруг это работает! Рад, что я наконец понял это. Thanx Remo!

ответ

1

У вас есть несколько вариантов:

  1. ли это как NopCommerce и сканирование классов настройки и вызовите метод регистрации с первого редактирования с помощью отражения.
  2. использовать расширение конвенций регистрировать все классы, реализующие ISettings с помощью пользовательского связывания генератора https://github.com/ninject/ninject.extensions.conventions/wiki/Projecting-Services-to-Bind
  3. использовать расширение конвенций регистрировать все классы, реализующие ISettings связывать все интерфейсы. И добавьте пользовательскую IActivationStrategy в Ninject, которая присваивает свойства, подобные NopCommerce.
Смежные вопросы