Проверьте, был ли когда-либо создан ленивый синглтон

Используя ninject, у меня есть такая привязка:

kernel.Bind<IFoo>().To<MyFoo>().InSingletonScope()
    .WithConstructorArgument("bar", new Action<IFoo>(foo =>
    {
        // some function here
    }));

То, что я хочу быть в состоянии сделать, это определить, стоит ли IFoo был построен без фактической попытки использовать его (так как это приведет к его созданию). Есть ли простой способ сделать это?

5 ответов

Решение

Можете добавить OnActivation(...) - который занимает Action в качестве параметра - для привязки. При этом вы можете делать все что угодно, в том числе устанавливая флаг в true.

Например:

static bool fooWasCreated = false;

kernel.Bind<IFoo>().To<MyFoo>()
      .InSingletonScope()
      .OnActivation(fooInstance => fooWasCreated = true);

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

Я думаю, что это вопрос применения правильных шаблонов, таких как шаблон прокси:

public class LazyFooProxy : IFoo
{
    private readonly Lazy<IFoo> foo;
    public LazyFooProxy(Lazy<IFoo> foo) {
        this.foo = foo;
    }

    public bool IsCreated {
        get { return this.foo.IsValueCreated; }
    }

    void IFoo.Method() {
        this.foo.Value.Method();
    }
}

Здесь мы создали LazyFooProxy прокси-класс, который может задержать создание IFoo и это также позволяет проверить, был ли создан foo (вызывая Lazy<T>.IsValueCreated имущество).

Теперь вы можете сделать следующую регистрацию:

var lazyFoo = new LazyFooProxy(new Lazy<IFoo>(kernel.Get<MyFoo>));
kernel.Bind<IFoo>().ToInstance(lazyFoo);
kernel.Bind<MyFoo>().InSingletonScope();

Теперь вы можете использовать LazyFooProxy.IsCreated свойство проверить MyFoo был создан или нет.

Вполне возможно, если вы покопаетесь во внутренних органах Ninject, то сможете найти способ найти объекты, которые будут там только после того, как эта привязка будет активирована. Но проще настроить привязку к фабричному методу, который устанавливает флаг, который вы можете проверить.

kernel.Bind<IFoo>().ToMethod(
    kernel => {
        Tracker.FooIsInitialized = true;
        return new MyFoo(kernel.Get<IDependency>());
    })
    .InSingletonScope()
    .WithConstructorArgument("bar", new Action<IFoo>(foo =>
    {
        // some function here
    }));

Когда он создан, он запускает логическое значение, которое вы можете проверить на true/false и просто получить это значение

В общем-то

Это может показаться оффтопом, но вы можете найти несколько полезных реализаций синглтона (автор Jon Skeet) здесь.

Вопрос

Если я правильно понял, вам просто нужно добавить bool Свойство, указывающее, был ли создан экземпляр или нет. например:

public static bool IsCreated { get { return _instance != null; } }

Как бы это ни использовалось, оно должно быть сделано из резьбы..

Реализация обертки

public static class FooWrapper 
{
    public static bool IsCreated { get; private set; } // default false

    public static IFoo GetInstance()
    {
        IsCreated = true;

        // return the Singleton Instance of IFoo
    }
}

Убедитесь, что единственный способ получить доступ к вашему IFoo Экземпляр с FooWrapper.GetInstance()

Другие вопросы по тегам