Внедрить IKernel как собственность в Ninject - PullRequest
0 голосов
/ 27 июня 2011

Я использую интерфейс средства разрешения зависимостей в общих библиотеках в качестве абстракции.Это позволяет мне гибко переключаться между контейнерами.Учитывая интерфейсы и статический класс IoC ниже, мне нужно инициализировать IoC с фабрикой без передачи IKernel от глобального asax.

См. Ниже, как я использую базу NinjectHttpApplication длясоздайте ядро ​​Ninject.

Вот проблема;свойство IKernel в CtsDependencyFactory всегда null.

Разве Ninject не внедряет себя таким образом?Должен ли я использовать другой метод для передачи IKernel на завод?Я не смог найти статический класс, такой как ObjectFactory в StructureMap в Ninject, чтобы получить ссылку на распознаватель.

Любая помощь приветствуется.

public interface IResolveDependency
{
    T Resolve<T>();
    T Resolve<T>(params object[] parameters);
    T Resolve<T>(string name);
    T Resolve<T>(string name, params object[] parameters);
    object Resolve(Type type);
    IEnumerable<T> ResolveAll<T>();
    void Clear();
}

public interface IResolveDependencyFactory
{
    IResolveDependency CreateInstance();
}

public class CtsDependencyResolver : IResolveDependency
{
    private readonly IKernel m_kernel;

    public CtsDependencyResolver(IKernel kernel)
    {
        m_kernel = kernel;
    }

    #region Implementation of IResolveDependency

    // removed for brevity

    #endregion
}

public class CtsDependencyFactory : IResolveDependencyFactory
{
    [Inject]
    public IKernel Kernel { get; set; }

    #region Implementation of IResolveDependencyFactory

    public IResolveDependency CreateInstance()
    {
        return new CtsDependencyResolver(Kernel);
    }

    #endregion
}

public static class IoC
{
public static IResolveDependency DependencyResolver { get; private set; }

public static void InitilizeWith(IResolveDependencyFactory factory)
{
    DependencyResolver = factory.CreateInstance();
}

public static void Register<T>(T instance)
{
    if (DependencyResolver is IRegisterDependency)
        ((IRegisterDependency)DependencyResolver).Register(instance);
    else
        throw new InvalidOperationException("cannot register service");
}

public static T Resolve<T>(string name)
{
    return DependencyResolver.Resolve<T>(name);
}

public static T Resolve<T>(string name, params object[] parameters)
{
    return DependencyResolver.Resolve<T>(name, parameters);
}

public static T Resolve<T>()
{
    return DependencyResolver.Resolve<T>();
}

public static T Resolve<T>(params object[] parameters)
{
    return DependencyResolver.Resolve<T>(parameters);
}

public static object Resolve(Type type)
{
    return DependencyResolver.Resolve(type);
}

public static IEnumerable<T> ResolveAll<T>()
{
    return DependencyResolver.ResolveAll<T>();
}

public static void Clear()
{
    DependencyResolver.Clear();
}
}

public class MvcApplication : NinjectHttpApplication
{
    private IKernel m_kernel;

    // removed stuff 

    protected override void OnApplicationStarted()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        IoC.InitilizeWith(new CtsDependencyFactory());
    }

    protected override IKernel CreateKernel()
    {
        var modules = new INinjectModule[]
                          {
                              new FormHandlerModule()
                          };

        m_kernel = new StandardKernel(modules);

        return m_kernel;
    }
}

Спасибо

1 Ответ

5 голосов
/ 27 июня 2011

Вы неправильно используете NInject (или любой другой DI-контейнер).То, что вы делаете, - это использование сервисного локатора, который, кажется, решает вашу проблему разрешения нужной вам зависимости, но просто скрывает ее.Если вы будете следовать RRR , вы позволите контейнеру справиться с бременем разрешения зависимостей, необходимых вашим классам.

Почему использование локатора служб является анти-шаблоном?

Наконец, разрешая зависимости вручную, вы фактически удаляете все шансы вычеркнуть зависимости.Является ли это проблемой для вас, кто знает.Это решается с помощью инжектора конструктора.

Относительно вашей проблемы с заменой контейнеров.Если вы не используете более одного контейнера для каждой проблемы (чего нет, нет), то вам следует разрешить только корневой компонент вашего проекта и позволить контейнеру вступить во владение.После того, как все сказано и сделано, ваш код не должен знать, что имеется контейнер.

Я предлагаю прочитать Внедрение зависимостей в .NET от Mark Seemann.

...