Используя StructureMap и IDependencyResolver, нельзя использовать интерфейс для строго типизированного представления и создавать действие - PullRequest
2 голосов
/ 06 февраля 2011

У меня новый проект, asp.net mvc 3.

Это все довольно стандартно, используя StructureMap и Nhibernate.

У меня есть 3 проекта, ядро, инфраструктура и пользовательский интерфейс.

Проводка StructureMap работает нормально, действие Index на контроллере Sample работает отлично.

Но в моем представлении создания я установил @model как что-то вроде

@model Project.Core.Domain.ISample

На контроллере у меня нормальный метод записи:

    [HttpPost]
    public ActionResult Create(ISample sample)
    {
        try
        {
            _repo.Save(sample);

            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }

Но я продолжаю получать сообщение «Невозможно создать экземпляр интерфейса». ошибка.

Последние выполненные строки в стеке:

[MissingMethodException: не удается создать экземпляр интерфейса.] System.RuntimeTypeHandle.CreateInstance (тип RuntimeType, логический publicOnly, логический noCheck, логический и canBeCached, RuntimeMethodHandleInternal & ctor, логический & bNeedSecurityCheck) +0 System.RuntimeType.CreateInstanceSlow (логическое значение publicOnly, логическое значение skipCheckThis, логическое значение fillCache) +98 System.RuntimeType.CreateInstanceDefaultCtor (логическое значение publicOnly, логическое значение skipVisibilityChecks, логическое значение skipCheckThis, логическое значение fillCache) +241 System.Activator.CreateInstance (тип Type, логический непубличный тип) +69 System.Web.Mvc.DefaultModelBinder.CreateModel (ControllerContext controllerContext, ModelBindingContext bindingContext, Тип modelType) +199 System.Web.Mvc.DefaultModelBinder.BindComplexModel (ControllerContext controllerContext, ModelBindingContext bindingContext) +572 System.Web.Mvc.DefaultModelBinder.BindModel (ControllerContext controllerContext, ModelBindingContext bindingContext) +449 System.Web.Mvc.ControllerActionInvoker.GetParameterValue (ControllerContext controllerContext, ParameterDescriptor параметрDescriptor) + 317

Я бы ожидал, что mvc будет использовать DependencyResolver для внутреннего использования, если он это сделает, он сможет создать конкретный экземпляр моего интерфейса ISample ... но есть большая вероятность, что я что-то понял совершенно неправильно, и это не имеет смысла ...

Если я внесу это простое изменение в контроллер, все будет работать нормально:

public ActionResult Create(Sample sample)

Я могу ошибаться, но мне это кажется неправильным, все остальное может использовать интерфейс для общения, зачем мне использовать конкретный класс в действии Create? Это лишило бы меня той гибкости, которую дал мне интерфейс.

Кто-нибудь имеет какие-либо идеи о том, как действовать, или я не на том пути?

Спасибо за внимание.

Вот как я получил то, что хотел с помощью Дарина

Я создал новый GenericModelBinder (возможно, имя могло бы быть лучше)

    public class GenericModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        var obj = DependencyResolver.Current.GetService(modelType);
        return base.CreateModel(controllerContext, bindingContext, obj.GetType());
    }
}

И в global.asax я добавил:

ModelBinders.Binders.DefaultBinder = new GenericModelBinder();

Спасибо за вашу помощь!

1 Ответ

0 голосов
/ 06 февраля 2011

Вам нужно будет написать пользовательский механизм связывания для типа ISample, чтобы это работало.ASP.NET MVC использует связыватель модели по умолчанию, когда он вызывает действие контроллера для создания экземпляров параметров действия из значений запроса.

public class MyISampleModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // Here you need to return the proper instance of the ISample interface
        // based on the request values or some other rules you need
    }
}

, а затем в Application_Start зарегистрируйте это связующее:

ModelBinders.Binders.Add(typeof(ISample), new MyISampleModelBinder());
...