我正在寻找在创建自定义属性时绕过属性参数限制的方法。具体来说,我有一个自定义DisplayName属性,该属性从数据库中检索数据,然后确定在视图上的LabelFor帮助程序中显示的内容。这是更大原型的一部分,因此代码优化是目前的次要问题。当我们准备开始开发实际项目时,我们将实现缓存和其他性能改进。我可以为我的实际问题提供一些上下文,但我希望答案能够适用于任何需要这样做的属性。
除了为某些私有属性分配参数外,构造函数不做任何工作:
public DisplayNameTranslationAttribute(string pageName = "", [CallerMemberName] string fieldName = "")
{
_pageName = pageName;
_fieldName = fieldName;
}
所有繁重的提升都发生在DisplayName覆盖方法中。原因是每次加载页面时都会调用DisplayName,而不是在第一次加载页面时只调用一次然后再也不会再调用一次的构造函数。
public override string DisplayName
{
get
{
string displayName = string.Empty;
_customerID = 1; //This needs be accessed or retrieved somehow, from somewhere
using (var db = new SomeDataEntities())
{
SomeData sd =
db.SomeDatas.FirstOrDefault(t => t.PageName == _pageName && t.FieldName == _fieldName);
SomeOtherData od = null;
if (sd != null)
{
od = sd.SomeOtherDatas.FirstOrDefault(c => c.CustomerID == _customerID);
displayName = Equals(od, null) ? sd.ColumnN : od.ColumnZ;
}
}
return displayName.IsNullOrWhiteSpace() ? _displayName : displayName;
}
}
如您所见,我现在正在将_customerID硬编码为1.我需要能够为_customerID提供实际值。我知道我不能将它作为参数直接传递给属性,所以我需要做的是发现规避这种限制的方法。是否有任何选项可以欺骗该属性,或者更有可能从内存中的其他位置检索ID?
答案 0 :(得分:3)
我永远无法想象Display属性会像这样被错过使用。请停止这样做!
如果标签名称来自DB,那么它可能是领域知识的一部分,不应该被视为视图逻辑(DisplayName
属性是)。
只需使用从控制器传递到视图的ViewModel获取此信息,而不必执行这些操作。控制器将从DB获取数据。简单!
// pseudo-code
public ActionResult Indes(int customerId)
{
var viewModel = new ViewModel();
viewModel.Value = dbContext.Customers.FirstOrDefault(c => c.CustomerId == customerId);
viewModel.DisplayName = dbContext.FieldNames.FirstOrDefault(f => f.Name == some condition);
return View(viewModel);
}
编辑:作为第二个想法,您可以尝试创建自己的属性,与显示属性完全分开,放置哪个字段应放在那里。然后实现DataAnnotationsModelMetadataProvider,它将为您提供正确的标签字段名称。
参见示例implementation of this Metadata Provider in my little app。这是从Jimmy Bogard无耻地偷走的。此实现不能满足您的需求,但会显示示例。