Ninject 2.0: добавление свойства без атрибута - PullRequest
9 голосов
/ 12 июля 2010

Есть ли способ использовать вложение свойств в Ninject 2 без использования атрибута [Inject]? Это создает зависимость от Ninject в классе, который будет подключен с его помощью, и я предпочитаю избегать ненужных зависимостей с моим контейнером IoC, поэтому я чаще использую Constructor Injection.

Полагаю, то же самое относится и к методу инъекций

Ответы [ 3 ]

7 голосов
/ 19 июля 2010

Я последовал совету Рубена и опубликовал небольшое сообщение в блоге о том, как этого добиться, но вот быстрый ответ:

Создание пользовательского атрибута:

public class InjectHereAttribute : Attribute
{
}

Целевой класс теперь будет выглядеть следующим образом:

public class Samurai
{
    [InjectHere]        
    public IWeapon Context { get; set; }
}

Теперь необходимо настроить Ninject для использования пользовательского атрибута, это можно сделать, создав реализацию IInjectionHeuristic, которая распознает пользовательский атрибут:

public class CustomInjectionHeuristic : NinjectComponent, IInjectionHeuristic, INinjectComponent, IDisposable
{
    public new bool ShouldInject(MemberInfo member)
    {
        return member.IsDefined(
          typeof(InjectHereAttribute),
          true);
    }
}

И, наконец, добавьте это поведение в ядро ​​Ninject, используя коллекцию Components, оно будет выполняться вдоль существующих компонентов, а именно реализации по умолчанию IInjectionHeuristic, что означает, что можно использовать атрибут по умолчанию или пользовательский атрибут.

// Add custom inject heuristic
kernel.Components.Add<IInjectionHeuristic, CustomInjectionHeuristic>();
4 голосов
/ 13 июля 2010

При создании вы можете передать ядру другой тип [attribute], который можно использовать вместо InjectAttribute, но вам все равно придется ссылаться на что-то централизованно OOTB.

Совсем недавно был похожий вопрос о создании PI без атрибутов - в пользовательский сканер не нужно добавлять OOTB (как непосредственно в интерфейсе конфигурации), а точки расширения (вы добавляете компонент, реализующий интерфейс Ninject, как вы строите свое ядро, которое определяет, как должен работать этот аспект, если поиск заданного атрибута - не то, что вам нужно), чтобы определить, куда вводить, основываясь на соглашении о конфигурации - ничто не мешает вам внести изменения в сканирование. только на имя атрибута (поэтому он не обязательно должен находиться в центральном месте).

Обратите внимание, что, как правило, внедрение конструктора в любом случае полезно по многим причинам, включая эту, и важно сохранять независимость от контейнера кода (даже если вы в настоящее время довольны одним из них!)

3 голосов
/ 14 августа 2010

Мне удалось сделать это с помощью эвристического класса:

public sealed class MyInjectionHeuristic : NinjectComponent, IInjectionHeuristic
{
        private static readonly IList<Type> 
            _propertyInjectible = 
                new List<Type>
                {
             typeof(IMyService),
                };

                    /// <summary>
      /// Returns a value indicating whether the specified member should be injected.
      /// </summary>
      /// <param name="member">The member in question.</param>
      /// <returns><c>True</c> if the member should be injected; otherwise <c>false</c>.</returns>
      public bool ShouldInject(MemberInfo member)
      {
       var info = member as PropertyInfo;

       if( member == null || info == null )
        return false;

       if (info.CanWrite)
        return _propertyInjectible.Contains(info.PropertyType);

       if( this.Settings == null )
        return false;

       var propList = member.GetCustomAttributes(this.Settings.InjectAttribute, true);

       return propList.Length > 0;
      }
}

При создании вашего ядра:

var heuristics = _kernel.Components.Get<ISelector>().InjectionHeuristics;
   heuristics.Add(new MyInjectionHeuristic());

Просто добавьте дополнительные типы в IList, когда вы хотите добавить другиеТипы через свойства.

...