Инъектор конструктора с TinyIoC - PullRequest
4 голосов
/ 09 февраля 2012

Я только что перешел с Ninject на TinyIoC для внедрения зависимостей, и у меня возникли проблемы с внедрением конструктора.

Мне удалось упростить его до следующего фрагмента:

public interface IBar { } 

public class Foo
{
    public Foo(IBar bar) { }
}

public class Bar : IBar
{
    public Bar(string value) { }
}

class Program
{
    static void Main(string[] args)
    {
        var container = TinyIoCContainer.Current;

        string value = "test";
        container.Register<IBar, Bar>().UsingConstructor(() => new Bar(value));

        var foo = container.Resolve<Foo>();
        Console.WriteLine(foo.GetType());
    }
}

, который вызывает исключение TinyIoCResolutionException с:

"Unable to resolve type: TinyIoCTestApp.Foo"

и внутри этого исключения естьцепочка внутренних исключений:

"Unable to resolve type: TinyIoCTestApp.Bar"
"Unable to resolve type: System.String"
"Unable to resolve type: System.Char[]"
"Value cannot be null.\r\nParameter name: key"

Что-то не так с тем, как я использую конструктор?Я понимаю, что могу позвонить

container.Register<IBar, Bar>(new Bar(value));

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

Есть идеи?

1 Ответ

7 голосов
/ 09 февраля 2012

Я не знаком с TinyIOC, но думаю, что смогу ответить на ваш вопрос.

UsingConstructor регистрирует лямбду, которая указывает на конструктор (ctor(string)), который TinyIOC будет использовать для автоматического внедрения конструктора. TinyIOC проанализирует аргументы конструктора, найдет аргумент типа System.String и попытается разрешить этот тип. Поскольку вы не зарегистрировали System.String явно (что, кстати, не следует), разрешить IBar (и, следовательно, Foo) не удалось.

Неправильное предположение, которое вы сделали, заключается в том, что TinyIOC выполнит вашу () => new Bar(value)) лямбду, чего не будет. Если вы посмотрите на метод UsingConstructor, вы увидите, что для него требуется Expression<Func<T>> вместо Func<T>.

То, что вы хотите, это зарегистрировать фабричный делегат, который делает создание. Я ожидаю, что TinyIOC будет содержать метод для этого. Это может выглядеть примерно так:

container.Register<IBar>(() => new Bar(value));
...