Как мне обрабатывать классы со статическими методами с помощью Ninject?

Как мне обрабатывать классы со статическими методами с помощью Ninject?

То есть в C # не может быть статических методов в интерфейсе, а Ninject работает на основе использования интерфейсов?

Мой вариант использования - это класс, в котором я хотел бы иметь статический метод для создания незаполненного экземпляра самого себя.

ИЗМЕНИТЬ 1

Чтобы добавить пример в классе TopologyImp, в методе GetRootNodes (), как мне создать несколько классов iNode для возврата? Смогу ли я создать их с помощью обычной практики кода или как-нибудь использовать Ninject? Но если я использую контейнер для создания, тогда разве я не дал этой библиотеке знаний о IOC?

public interface ITopology
{
    List<INode> GetRootNodes();
}


public class TopologyImp : ITopology
{
    public List<INode> GetRootNodes()
    {
        List<INode> result = new List<INode>();

        // Need code here to create some instances, but how to without knowledge of the container?
        // e.g. want to create a few INode instances and add them to the list and then return the list 
    }
}

public interface INode
{
    // Parameters
    long Id { get; set; }
    string Name { get; set; }
}

class NodeImp : INode
{
    public long Id
    {
        get { throw new NotImplementedException(); }
        set { throw new NotImplementedException(); }
    }

    public string Name
    {
        get { throw new NotImplementedException(); }
        set { throw new NotImplementedException(); }
    }
}


// Just background to highlight the fact I'm using Ninject fine to inject ITopology
public partial class Form1 : Form
{
    private ITopology _top;
    public Form1()
    {
        IKernel kernal = new StandardKernel(new TopologyModule());
        _top = kernal.Get<ITopology>();
        InitializeComponent();
    }
}

person Greg    schedule 26.04.2010    source источник


Ответы (1)


Если вы создаете синглтон или что-то в этом роде и пытаетесь внедрить зависимости, обычно вы вместо этого пишете свой код как обычный класс, не пытаясь добавить много (возможно, неправильного) кода, управляющего синглтоном, и вместо этого регистрируете объект InSingletonScope (v2 - вы не упомянули свою версию Ninject). Каждый раз, когда вы это делаете, у вас появляется на один класс меньше, который не обнаруживает своих зависимостей.

Если вы чувствуете себя особенно одурманенным и уверены, что хотите пойти против этого общего потока, основные инструменты, которые дает вам Ninject, - это Kernel.Inject, который можно использовать после того, как вы (или кто-то другой) newd создадите экземпляр, чтобы ввести зависимости. Но затем, чтобы определить местонахождение своего Kernelm, вы обычно будете использовать Service Locator, который, вероятно, вызовет столько же беспорядка, сколько и решит.

РЕДАКТИРОВАТЬ: Спасибо за продолжение - я вижу, что вам нужно. Вот хитрый способ приблизить автоматический заводской механизм autofac < / а>: -

/// <summary>
/// Ugly example of a not-very-automatic factory in Ninject
/// </summary>
class AutomaticFactoriesInNinject
{
    class Node
    {
    }

    class NodeFactory
    {
        public NodeFactory( Func<Node> createNode )
        {
            _createNode = createNode;
        }

        Func<Node> _createNode;
        public Node GenerateTree()
        {
            return _createNode();
        }
    }

    internal class Module : NinjectModule
    {
        public override void Load()
        {
            Bind<Func<Node>>().ToMethod( context => () => Kernel.Get<Node>() );
        }
    }

    [Fact]
    public void CanGenerate()
    {
        var kernel = new StandardKernel( new Module() );
        var result = kernel.Get<NodeFactory>().GenerateTree();
        Assert.IsType<Node>( result );
    }
}

Материал ToMethod - это конкретное приложение шаблона ToProvider - вот как вы сделаете то же самое через этот маршрут: -

    ...

    class NodeProvider : IProvider
    {
        public Type Type
        {
            get { return typeof(Node); }
        }
        public object Create( IContext context )
        {
            return context.Kernel.Get<Node>();
        }
    }

    internal class Module : NinjectModule
    {
        public override void Load()
        {
            Bind<Func<Node>>().ToProvider<NodeProvider>();
        }
    }

    ...

Я не обдумал это, хотя и не рекомендую это как хорошую идею - могут быть гораздо лучшие способы структурировать что-то вроде этого. @Mark Seemann? :П

Я считаю, что Unity и MEF также поддерживают вещи в этом направлении (ключевые слова: automatic factory, Func)

РЕДАКТИРОВАТЬ 2: более короткий синтаксис, если вы хотите использовать специфичные для контейнера атрибуты и перейти к внедрению свойств (даже если Ninject позволяет вам переопределить определенные атрибуты, я предпочитаю инъекцию конструктора):

    class NodeFactory
    {
        [Inject]
        public Func<Node> NodeFactory { private get; set; }
        public Node GenerateTree()
        {
            return NodeFactory();
        }
    }

РЕДАКТИРОВАТЬ 3: вам также необходимо знать об этом модуле Ninject от @Remo Gloor, который должен быть в версии 2.4

РЕДАКТИРОВАТЬ 4: Также перекрывается, но не имеет прямого отношения, тот факт, что в Ninject вы можете запросить IKernel в своем ctor / properties и ввести его (но это не работает напрямую в статическом методе).

person Ruben Bartelink    schedule 26.04.2010
comment
Привет, Рубен, я добавил некоторые пояснения к вопросу. Как бы вы сами создали экземпляры INode в этом случае? (т.е. см. этот момент в коде, который я прокомментировал) - спасибо - person Greg; 26.04.2010
comment
Спасибо, Рубен, мне придется позволить этому осознать. Я как бы обдумываю, какие ощутимые преимущества будет иметь этот подход по сравнению с обычным созданием классов в том месте, которое я указал в своем коде? Вы видите одну? Неужели это действительно нарушит концепцию IOC, если вы заметите, что во всех других областях вашего кода вы следовали подходу Ninject? - person Greg; 27.04.2010
comment
PS Верно ли, что Ninject не поддерживает это, а некоторые другие контейнеры IOC поддерживают? (просто упомяните автофак в ответе выше) - спасибо - person Greg; 28.04.2010
comment
Судя по моему быстрому поиску, кажется, что autofac поддерживает его изначально. Unity также поддерживает это, но я не смотрел, как это сделать. MEF поддерживает его, но в первую очередь это не контейнер DI (и, вероятно, его будет нелегко использовать без атрибутов). Не видел упоминания ни о каких других. Кроме того, хотя OOTB в Ninject нет способа, может быть расширение, и вы получите более убедительный ответ от коммиттеров на groups.google.com/group/ninject (или, может быть, здесь подслушивает @Ian Davis?) - person Ruben Bartelink; 28.04.2010
comment
Я думаю, что решение, которое я опубликовал, определенно стоит использовать вместо raw new s as 1) Вы сохраняете определенные привязки за пределами класса 2) вам не нужно иметь дело с беспорядком и путаницей, которые используют локатор служб (т. Е. Некоторые глобальное место, куда вы идете и запрашиваете зависимости), и 3) вы можете кодировать одинаково согласованным образом (без несоответствий в стиле управления зависимостями, искажающего ваш код). то есть, если вы не экстернализируете проблему таким образом, вы в конечном итоге выполните GlobalKernel.Get<T>() или new, за которым следует GlobalKernel.Inject( newed) - person Ruben Bartelink; 28.04.2010
comment
Сказав это ... если вы просто управляете простыми типами значений и можно изолировать дерево в его собственной области, тогда нет никакого запрета на использование старого доброго new! - и если вы позаботитесь об этом, код может оказаться проще. Используйте свое суждение, и все будет в порядке. - person Ruben Bartelink; 28.04.2010
comment
Я также добавил более короткий синтаксис, который может заставить вашу лодку плавать (хотя я давно перестал использовать инъекцию опоры (и специфичные для контейнера атрибуты) (но я чувствую, что вас беспокоит чистота и уместность, а не длина кода). ) - person Ruben Bartelink; 28.04.2010