asp.net mvc中的动态工厂

时间:2011-05-20 18:56:25

标签: asp.net-mvc-3

我有一种情况,我有8个对象都从一个对象继承。出于某些目的,这些对象必须是他们自己的类,但在初始创建时,它们没有任何不同。

它们不能作为基础对象创建,必须将它们作为自己的对象添加到数据库中。这是不容谈判的。

为此创建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);
   // ... 
}

看起来很简单,但它不起作用。我试过在ViewModel上放一个System.Type属性 - 它只是不起作用。我唯一能够开始工作的是使用一个巨大的switch语句,但这似乎是一种糟糕的方法。

有没有办法在没有过多冗余的情况下完成这项工作?

1 个答案:

答案 0 :(得分:1)

如何创建自定义模型绑定器:

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