C #, Autofac: NamedParameter не предоставлен в реестре <> - PullRequest
1 голос
/ 11 марта 2019

В данный момент я пробую некоторые функции автозапуска и борюсь с параметром NamedParameter.

Я создал очень простой пример, в котором IFoo реализуется с помощью HappyFoo и SadFoo.IFooUser ожидает объект IFoo в конструкторе и использует его для печати чего-либо на консоли.

Приведенный ниже код показывает, как я пытаюсь построить объект IFooUser, который должен использовать IFoo объект основан на значении «оценка».

        var builder = new ContainerBuilder();

        builder.RegisterType<NormalFooUser>().As<IFooUser>();

        builder.Register<IFoo>((context, parameters) =>
        {
            var score = parameters.Named<int>("score"); // ! Exception !
            if (score >= 100)
            {
                return new HappyFoo();
            } 
            return new SadFoo();
        });

        var container = builder.Build();

        using (var scope = container.BeginLifetimeScope())
        {
            scope.Resolve<IFooUser>(new NamedParameter("score", 90)).useFoo();
        }

К сожалению, когда я выполняю этот код, последовательность parameters не содержит никаких значений => Исключение!Когда я решаю IFoo, все работает нормально:

       scope.Resolve<IFoo>(new NamedParameter("score", 90)).foo(); // Works

Но я не хочу этого делать.Поэтому мне интересно, как я могу построить IFooUser с IFoo объектом, соответствующим 'партитуре' с NamedParameter.

Полный пример кода можно найти здесь как гист

Спасибо.

Ответы [ 2 ]

1 голос
/ 12 марта 2019

NamedParameter предназначен для настройки запрошенного компонента, а не всего графа зависимостей, параметр не распространяется в течение всего процесса регистрации, он не является параметром context .

Если вы хотите иметь контекст , вы можете реализовать такой компонент, который будет хранить некоторые свойства.

// interface 
interface IContext {
    T Get<T>(String name); 
    void Set<T>(String name, T value); 
}

// registration 
builder.RegisterType<FooContext>().As<IContext>();
builder.Register<IFoo>(c =>
{
    var score = c.Resolve<IContext>().Get<Int32>("score"); 
    if (score >= 100)
    {
        return new HappyFoo();
    }
    return new SadFoo();
});


// usage 
using (ILifetimeScope scope = container.BeginLifetimeScope())
{
    scope.Resolve<IContext>().Set("score", 90); 
    scope.Resolve<IFooUser>().useFoo();
}

Преимущество этого подхода состоит в том, что вы можете установитьсвойство context всякий раз, когда вы хотите в своей текущей области жизни.Вы также можете представить себе реализацию без метода Set, который будет извлекать значение на основе того, что вы хотите.

Другой способ сделать то же самое - использовать зависимость Func<Int32, IFoo> и методы TypedAs

builder.Register<IFoo>((c, p) =>
{
    Int32 score = p.TypedAs<Int32>(); 
    if (score >= 100)
    {
        return new HappyFoo();
    }
    return new SadFoo();
});

и, конечно, вы должны изменить интерфейс IFooUser и реализацию

public class NormalFooUser : IFooUser
{
    private readonly Func<Int32, IFoo> _fooBuilder;

    public NormalFooUser(Func<Int32,IFoo> fooBuilder)
    {
        _fooBuilder = fooBuilder;
    }

    public void useFoo(Int32 score)
    {
        _fooBuilder(score).foo();
    }
}
0 голосов
/ 12 марта 2019
scope.Resolve<IFooUser>(new NamedParameter("score", 90))

сообщает Autofac, что он должен использовать параметр score для создания экземпляра, зарегистрированного как IFooUser, но на самом деле это не нужно - его зависимости IFoo это нужно.Autofac не передает эти параметры автоматически в зависимости от типа, вам нужно сделать это самостоятельно, просто передавая параметры при регистрации для IFooUser

builder.Register((c, p) => new NormalFooUser(c.Resolve<IFoo>(p))).As<IFooUser>();

Этот фрагмент передает все параметры, используемые для разрешения IFooUser,Вы можете ограничить это только этими необходимыми

builder.Register((c, p) => new NormalFooUser(c.Resolve<IFoo>(new NamedParameter("score", p.Named<int>("score"))))).As<IFooUser>();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...