Ninject WithConstructorArgument: нет доступных привязок, и тип не является самопривязываемым

Мое понимание WithConstructorArgument, вероятно, ошибочно, потому что следующее не работает:

У меня есть служба, назовем ее MyService, конструктор которой принимает несколько объектов и строковый параметр с именем testEmail. Для этого строкового параметра я добавил следующую привязку Ninject:

string testEmail = "[email protected]";
kernel.Bind<IMyService>().To<MyService>().WithConstructorArgument("testEmail", testEmail);

Однако при выполнении следующей строки кода я получаю исключение:

var myService = kernel.Get<MyService>();

Вот исключение, которое я получаю:

Ошибка активации строки. Нет доступных привязок, и тип не является самопривязываемым. Путь активации:
2) Внедрение строки зависимости в параметр testEmail конструктора типа MyService
1) Запрос MyService

Предложения:
1) Убедитесь, что вы определили привязку для строки.
2) Если привязка была определена в модуле, убедитесь, что модуль загружен в ядро.
3) Убедитесь, что вы случайно не создал более одного ядра.
4) Если вы используете аргументы конструктора, убедитесь, что имя параметра совпадает с именем параметра конструктора.
5) Если вы используете автоматическую загрузку модуля, убедитесь, что путь поиска и фильтры верны.

Что я здесь делаю неправильно?

ОБНОВЛЕНИЕ:

Вот конструктор MyService:

[Ninject.Inject]
public MyService(IMyRepository myRepository, IMyEventService myEventService, 
                 IUnitOfWork unitOfWork, ILoggingService log,
         IEmailService emailService, IConfigurationManager config,
         HttpContextBase httpContext, string testEmail)
{
    this.myRepository = myRepository;
    this.myEventService = myEventService;
    this.unitOfWork = unitOfWork;
    this.log = log;
    this.emailService = emailService;
    this.config = config;
    this.httpContext = httpContext;
    this.testEmail = testEmail;
}

У меня есть стандартные привязки для всех типов параметров конструктора. Только 'string' не имеет привязки, а HttpContextBase имеет привязку, которая немного отличается:

kernel.Bind<HttpContextBase>().ToMethod(context => new HttpContextWrapper(new HttpContext(new MyHttpRequest("", "", "", null, new StringWriter()))));

и MyHttpRequest определяется следующим образом:

public class MyHttpRequest : SimpleWorkerRequest
{
    public string UserHostAddress;
    public string RawUrl;

    public MyHttpRequest(string appVirtualDir, string appPhysicalDir, string page, string query, TextWriter output)
    : base(appVirtualDir, appPhysicalDir, page, query, output)
    {
        this.UserHostAddress = "127.0.0.1";
        this.RawUrl = null;
    }
}

person Jean-François Beauchamp    schedule 20.11.2012    source источник
comment
Не могли бы вы показать целевой конструктор MyService? Указанное имя должно совпадать с именем аргумента cinstructor.   -  person horgh    schedule 20.11.2012
comment
@KonstantinVasilcov Смотрите мое обновление выше. Я только что добавил код для моего конструктора.   -  person Jean-François Beauchamp    schedule 20.11.2012
comment
У вас есть привязки для каждого из этих интерфейсов?   -  person horgh    schedule 20.11.2012
comment
@KonstantinVasilcov Я дважды проверил и да. Все они выглядят как kernel.Bind‹IEmailService›().To‹EmailService›(); за исключением привязки HttpContextBase, которую я сейчас показываю в разделе «Обновление» моего вопроса выше.   -  person Jean-François Beauchamp    schedule 20.11.2012
comment
Как по мне, привязка аргумента string работает хорошо. Я не мог привязать HttpContextBase к методу... Мне удалось заставить все работать, только поменяв привязку HttpContextBase к этому kernel.Bind<IServiceProvider>().ToMethod(...)   -  person horgh    schedule 20.11.2012
comment
@KonstantinVasilcov Для теста я только что создал еще один конструктор без параметра testEmail и украсил его атрибутом [Ninject.Inject]. Теперь он работает, за исключением других ошибок, которые будут обнаружены позже, но инъекция работает, даже для HttpContextBase для меня. Тем не менее, я хотел бы иметь возможность заставить этот параметр testEmail работать в какой-то момент.   -  person Jean-François Beauchamp    schedule 20.11.2012
comment
На самом деле я использую Ninject 3.0, возможно, это может вызвать некоторые различия... Ну, вы пробовали удалить HttpContextBase и использовать аргумент string?   -  person horgh    schedule 20.11.2012
comment
@KonstantinVasilcov Я использую Ninject v3.0.1.10. Я не пытался удалить HttpContextBase из конструктора. Это будет следующая вещь, которую я попробую.   -  person Jean-François Beauchamp    schedule 20.11.2012
comment
Вы уверены, что у вас только одно ядро? Это то же самое ядро, где вы установили WithConstructorArgument и откуда вызвали var myService = kernel.Get<MyService>(); (можете проверить при отладке методом GetHascode())?   -  person nemesv    schedule 20.11.2012
comment
@KonstantinVasilcov Я попытался удалить HttpContextBase из конструктора и сделать testEmail первым параметром конструктора вместо последнего, но все равно получаю ту же ошибку.   -  person Jean-François Beauchamp    schedule 20.11.2012
comment
@nemesv Я только что проверил, и да, у меня только одно ядро. Я устанавливаю разные точки останова, и везде kernel.GetHashcode() дает мне одно и то же число. Спасибо, что сообщили мне, как это проверить.   -  person Jean-François Beauchamp    schedule 20.11.2012
comment
Я думаю, что вы Get<> не того типа... попробуйте с var myService = kernel.Get<IMyService>(); обратите внимание на IMyService   -  person nemesv    schedule 20.11.2012
comment
@nemesv Вот и все. Я передал класс вместо интерфейса в kernel.Get‹›(). Большое спасибо Немесв! Вы должны опубликовать повторно то, что вы написали в качестве ответа, чтобы я мог отметить это как решение моего вопроса.   -  person Jean-François Beauchamp    schedule 20.11.2012
comment
Да, действительно, это было очень странное проявление очень простой проблемы.   -  person nemesv    schedule 20.11.2012


Ответы (2)


С заявлением:

var myService = kernel.Get<MyService>();

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

Таким образом, он не будет использовать ваш WithConstructorArgument для разрешения "testEmail", потому что он будет использоваться только с Bind<IMyService>(), поэтому вы получаете исключение.

Итак, если вы зарегистрировали свой MyService с помощью:

string testEmail = "[email protected]";
kernel.Bind<IMyService>().To<MyService>()
      .WithConstructorArgument("testEmail", testEmail);

Затем вы должны разрешить его через зарегистрированный интерфейс (IMyService):

var myService = kernel.Get<IMyService>();
person nemesv    schedule 20.11.2012
comment
Кроме того, убедитесь, что внедрение класса не было случайно помечено как абстрактный ;). Ошибка не скажет вам. - person jwize; 17.07.2019

Хотя у nemesv есть правильный ответ, я столкнулся с той же ошибкой, и решением для меня была мошенническая DLL в моем /bin. Я провел рефакторинг и удалил/переместил некоторые классы, которые все еще присутствовали в моей старой DLL. Решение - удалите старую DLL.

person jrap    schedule 19.07.2016