Поддерживает ли Ninject Func (автоматически сгенерированная фабрика)? - PullRequest
21 голосов
/ 30 января 2011

Autofac автоматически генерирует фабрики для Func<T>;Я даже могу передать параметры.

public class MyClass
{
    public MyClass(Func<A> a, Func<int, B> b)
    {
        var _a = a();
        var _b = b(1);
    }
}

Могу ли я сделать то же самое с Ninject?Если нет, какой обходной путь я могу применить?

Спасибо.

Обновление :

Только что нашел этот пост, кажется, ответ нет:

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

1 Ответ

29 голосов
/ 31 января 2011

NB Ninject 3.0 и более поздних версий полностью поддерживается с помощью пакета Ninject.Extensions.Factory, см. Вики: - https://github.com/ninject/ninject.extensions.factory/wiki


РЕДАКТИРОВАТЬ: NB: в Ninject 2.3 есть реализация Bind<T>().ToFactory() (это не полностью поддерживаемый тестовый выпуск, но доступен с сервера CodeBetter )

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

public class FuncModule : NinjectModule
{
    public override void Load()
    {
        this.Kernel.Bind(typeof(Func<>)).ToMethod(CreateFunc).When(VerifyFactoryFunction);
    }

    private static bool VerifyFactoryFunction(IRequest request)
    {
        var genericArguments = request.Service.GetGenericArguments();
        if (genericArguments.Count() != 1)
        {
            return false;
        }

        var instanceType = genericArguments.Single();
        return request.ParentContext.Kernel.CanResolve(new Request(genericArguments[0], null, new IParameter[0], null, false, true)) ||
               TypeIsSelfBindable(instanceType);
    }

    private static object CreateFunc(IContext ctx)
    {
        var functionFactoryType = typeof(FunctionFactory<>).MakeGenericType(ctx.GenericArguments);
        var ctor = functionFactoryType.GetConstructors().Single();
        var functionFactory = ctor.Invoke(new object[] { ctx.Kernel });
        return functionFactoryType.GetMethod("Create").Invoke(functionFactory, new object[0]);
    }

    private static bool TypeIsSelfBindable(Type service)
    {
        return !service.IsInterface
               && !service.IsAbstract
               && !service.IsValueType
               && service != typeof(string)
               && !service.ContainsGenericParameters;
    }

    public class FunctionFactory<T>
    {
        private readonly IKernel kernel;

        public FunctionFactory(IKernel kernel)
        {
            this.kernel = kernel;
        }

        public Func<T> Create()
        {
            return () => this.kernel.Get<T>();
        }
    }
}
...