динамическая фабрика в asp.net mvc - PullRequest
1 голос
/ 20 мая 2011

У меня есть ситуация, когда у меня есть 8 объектов, которые все наследуются от одного объекта.Для определенных целей эти объекты должны быть их собственными классами, но при первоначальном создании 1004 * в них нет ничего другого.

Они не могут быть созданы как базовый объект, они должны быть добавлены в базу данных как их собственный объект.Это не подлежит обсуждению.

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

abstract class Base {
  Guid Id { get; set; }
  string Name { get; set; }
  string Description { get; set; }
}

class Alpha : Base { // }
class Beta : Base { // }
class Sigma : Base { // }
class Delta : Base { // }

class ObjectViewModel {
  string Name { get; set; }
  string Description { get; set; }
}


ActionResult Create(){
 return View();
}

[HttpPost]
ActionResult Create(ObjectViewModel model) {
   // determine which type needs to be created
   Factory.Create(model); // the factory will create the right object based on the type
   repository.Add(factoryCreatedObject);
   // ... 
}

Это кажется достаточно простым, но это просто не работает.Я попытался поместить свойство System.Type в ViewModel - оно просто не работает.Единственное, что мне удалось получить - это использовать гигантское выражение switch, но это кажется плохим подходом.

Можно ли как-нибудь это сделать без чрезмерной избыточности?

1 Ответ

1 голос
/ 21 мая 2011

Как насчет создания пользовательского связывателя модели:

public class BaseModelBinder : DefaultModelBinder
{
    private Type _type;

    protected override ICustomTypeDescriptor GetTypeDescriptor(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        return TypeDescriptor.GetProvider(_type).GetTypeDescriptor(_type);
    }

    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        var result = bindingContext.ValueProvider.GetValue("type");
        if (result == null)
        {
            throw new Exception("please provide a valid type parameter");
        }

        _type = Type.GetType(result.AttemptedValue);
        if (_type == null || !typeof(Base).IsAssignableFrom(_type))
        {
            throw new Exception("please provide a valid type parameter");
        }
        return Activator.CreateInstance(_type);
    }
}

, который вы бы зарегистрировали в Application_Start:

ModelBinders.Binders.Add(typeof(Base), new BaseModelBinder());

, и теперь вы можете выполнить следующее действие контроллера:

public ActionResult Foo(Base model)
{
    ... 
}

Теперь, когда вы вызываете это действие, просто передайте дополнительный параметр type, указывающий конкретный экземпляр, который вы хотите создать.Например:

http://localhost:1203/?type=MvcApplication1.Models.Alpha&Id=21EC2020-3AEA-1069-A2DD-08002B30309D&Name=Test&Description=Somedescription&AlphaProp=alpha
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...