在我的模型类中,我有多个属性是“受保护的内部集”。创建这些属性后,它们将无法修改。话虽如此,我很难创建一个模型绑定器,允许在创建时设置这些属性。为了能够只设置一次这些属性,最好的方法是什么?
答案 0 :(得分:1)
不幸的是,这不是你可以自动完成的事情。您必须为每种类型创建一个唯一的模型绑定器,然后使用构造函数参数创建对象。
答案 1 :(得分:1)
我是使用自定义模型绑定器完成的。我不仅拥有私有的setter,而且我的MVC操作的参数是一个接口,而且我没有无参数的构造函数(三元组!);这些都不适用于默认的模型绑定器。
在您的情况下,您只需为您的类型制作自定义模型活页夹。使用默认值创建类的新实例。然后只需使用Reflection在类上设置属性。反射方法不关心属性的可访问性。像这样:
// assuming your class looks like this
public class MyClass
{
public int MyInt { get; private set; }
public string MyString { get; private set; }
public MyClass(int myInt, string myString)
{
MyInt = myInt;
MyString = myString;
}
}
// model binder is like this
public class MyModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext,
ModelBindingContext bindingContext,
Type modelType)
{
// initialize with default values, they will be overwritten
MyClass myClass = new MyClass(default(int), default(string));
// get the reflection info on the int property
PropertyInfo intProperty = typeof(MyClass).GetProperty("MyInt");
// get the int value from the request
int myIntValue = int.Parse(bindingContext.ValueProvider
.GetValue(intProperty.Name).AttemptedValue);
// btw, attempted value is a string
// set the property value, SetValue ignores accessibility modifiers
intProperty.SetValue(myClass, myIntValue, null);
// do the same stuff for MyString property
PropertyInfo stringProperty = typeof(MyClass).GetProperty("MyString");
string myStringValue = bindingContext.ValueProvider
.GetValue(stringProperty.Name).AttemptedValue;
stringProperty.SetValue(myClass, myStringValue, null);
return myClass;
}
}
// Your controller action is like this
public ActionResult MyAction([ModelBinder(typeof(MyModelBinder))]
MyClass myClass)
{
...
}
我想你可以将正确的值传递给构造函数而不使用反射来设置它们:
...
int myIntValue = int.Parse(bindingContext.ValueProvider
.GetValue(intProperty.Name).AttemptedValue);
string myStringValue = bindingContext.ValueProvider
.GetValue(stringProperty.Name).AttemptedValue;
MyClass myClass = new MyClass(myIntValue, myStringValue);
...
但是如果您需要做更多,反射可以让您绕过访问修饰符限制(当然有效的基础结构原因!:D)。在我的例子中,我不想为每个可以实现接口的类编写模型绑定器,所以我使用了更多的反射来匹配类,找到一个构造函数,将默认值传递给它,然后循环遍历每个属性该类并从请求值中设置它。我有一个单独的方法,可以在基于它运行操作之前验证消息。
答案 2 :(得分:0)
只有在尚未设置私有字段的情况下,您是否可以设置受保护的设置方法?
public string PropertyName
{
get
{
return this.privateField;
}
protected set
{
if (this.privateField == null)
{
this.privateField = value;
}
}
}
private string privateField;