在运行时向对象实例添加属性
Add Attributes to instance of object at runtime
我正在尝试生成一个包含来自数据库的问题的动态表单。
每个问题都有其类型和其他 属性.
我的例子类:
public class QuestionnaireBase
{
public string Text { get; set; }
public int Sequence { get; set; }
}
public abstract class Question : QuestionnaireBase
{
public bool IsRequired { get; set; }
public bool WithComment { get; set; }
public abstract object Answer { get; set; }
}
public class TextQuestion : Question
{
public string DefaultText { get; set; }
public int MaxLength { get; set; }
public override object Answer { get; set; }
}
我想将一些属性(DisplayAttribute、MaxLenght)添加到 Answer 字段,这样当我使用 EditorFor 和 LabelFor 时,这些属性会被考虑在内。
在检索我的问题时,我尝试在我的字段上添加一个属性 'Answer'(这里是一个存根):
Enumerable.Range(1, 5).Select(questionSeq => new TextQuestion {
Text = string.Format("Question {0}" questionSeq),
Answer = "TEXTVALUE" + questionSeq
}).Select(w => {
var skd = new DisplayAttribute();
skd.Name = w.Text;
TypeDescriptor.AddAttributes(w.Answer,skd );
return w;
})
现在,在我的视图中,我想使用 LabelFor 来显示此 DisplayAttribute:
@Html.LabelFor(model => model.Questions[questionIndex].Answer)
这会将 'Answer' 输出为文本。
我可以通过这样做绕过这个问题:
@{
var attribute =
TypeDescriptor.GetAttributes(Model.Questions[questionIndex].Answer)[typeof(DisplayAttribute)];
var displayAttribute = ((DisplayAttribute) attribute);
}
@Html.LabelFor(model =>
model.Questions[questionIndex].Answer, displayAttribute.Name)
我的第一个猜测是,LabelFor 会在我的类型上使用 DisplayAttribute,而不是在我的实例上。
显然,我不想为每个属性都做这项工作,否则在运行时创建属性完全没用。
我该怎么做才能解决这个问题?
我想对 MaxLenghtAttribute/Range 做同样的事情。
感谢您的宝贵时间
我认为您无法完全做到这一点,因为属性是静态元数据。
Can attributes be added dynamically in C#?
一种可能的解决方法是创建您自己的自定义属性,实现所有可能的验证(MaxLength、Range 等),并在对象上附加一些触发器 enable/disable。这将处理验证,但不会处理您问题中提到的特定实例 (Html.LabelFor + DisplayName)。为此,您可以创建自己的扩展方法来访问 DisplayName 属性,其方式与将其添加到实例的方式相同。
我正在尝试生成一个包含来自数据库的问题的动态表单。 每个问题都有其类型和其他 属性.
我的例子类:
public class QuestionnaireBase
{
public string Text { get; set; }
public int Sequence { get; set; }
}
public abstract class Question : QuestionnaireBase
{
public bool IsRequired { get; set; }
public bool WithComment { get; set; }
public abstract object Answer { get; set; }
}
public class TextQuestion : Question
{
public string DefaultText { get; set; }
public int MaxLength { get; set; }
public override object Answer { get; set; }
}
我想将一些属性(DisplayAttribute、MaxLenght)添加到 Answer 字段,这样当我使用 EditorFor 和 LabelFor 时,这些属性会被考虑在内。
在检索我的问题时,我尝试在我的字段上添加一个属性 'Answer'(这里是一个存根):
Enumerable.Range(1, 5).Select(questionSeq => new TextQuestion {
Text = string.Format("Question {0}" questionSeq),
Answer = "TEXTVALUE" + questionSeq
}).Select(w => {
var skd = new DisplayAttribute();
skd.Name = w.Text;
TypeDescriptor.AddAttributes(w.Answer,skd );
return w;
})
现在,在我的视图中,我想使用 LabelFor 来显示此 DisplayAttribute:
@Html.LabelFor(model => model.Questions[questionIndex].Answer)
这会将 'Answer' 输出为文本。 我可以通过这样做绕过这个问题:
@{
var attribute =
TypeDescriptor.GetAttributes(Model.Questions[questionIndex].Answer)[typeof(DisplayAttribute)];
var displayAttribute = ((DisplayAttribute) attribute);
}
@Html.LabelFor(model =>
model.Questions[questionIndex].Answer, displayAttribute.Name)
我的第一个猜测是,LabelFor 会在我的类型上使用 DisplayAttribute,而不是在我的实例上。
显然,我不想为每个属性都做这项工作,否则在运行时创建属性完全没用。
我该怎么做才能解决这个问题? 我想对 MaxLenghtAttribute/Range 做同样的事情。 感谢您的宝贵时间
我认为您无法完全做到这一点,因为属性是静态元数据。
Can attributes be added dynamically in C#?
一种可能的解决方法是创建您自己的自定义属性,实现所有可能的验证(MaxLength、Range 等),并在对象上附加一些触发器 enable/disable。这将处理验证,但不会处理您问题中提到的特定实例 (Html.LabelFor + DisplayName)。为此,您可以创建自己的扩展方法来访问 DisplayName 属性,其方式与将其添加到实例的方式相同。