【问题标题】:Circumventing the const requirement of parameters for a custom attribute规避自定义属性参数的 const 要求
【发布时间】:2014-01-31 20:16:02
【问题描述】:

我正在寻找在创建自定义属性时规避属性参数限制的方法。具体来说,我有一个自定义的 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?

【问题讨论】:

    标签: c# asp.net-mvc model-view-controller custom-attributes


    【解决方案1】:

    我无法想象 Display 属性会被这样误用。请停止这样做!

    如果标签名称取自 DB,那么它可能是领域知识的一部分,不应被视为视图逻辑(DisplayName 属性是)。

    不必做这些黑客攻击,只需使用从控制器传递到视图的 ViewModel 获取这些信息。控制器将从数据库中获取数据。简单!

    // 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 偷来的。此实现不满足您的需求,但显示了一个示例。

    【讨论】:

    • 这是我的后备计划。不幸的是,这将应用于即将到来的项目中的几乎每个 ViewModel,并且我们需要构建的页面数量并非微不足道。这实际上会使我们构建的每个 ViewModel 的大小翻倍。这使得实现和维护变得更加麻烦,我希望通过编写属性并装饰所有内容来避免。
    • 但是,如果最终答案真的是,“这是个糟糕的主意!”我不会反对的。
    • 是的,这是个糟糕的主意!不幸的是,您的任务没有简单的方法。要么是难以维护的黑客负载,要么是额外属性的负载。我可以想办法在视图模型中实现一些接口,并有一个过滤器来检测接口/属性并将值填充到模型中。但是属性本身不能这样做。
    • 你有具体帖子的链接吗?在网站上搜索或通过 Google 上的网站搜索对我没有任何帮助。我可能正在寻找错误的东西。
    • 你是说吉米的帖子?没有关于该主题的帖子。 Model Metada 提供者取自他的书中,但它并没有做你想做的事,所以需要自己实现反射/属性检测
    猜你喜欢
    • 2012-03-09
    • 1970-01-01
    • 2011-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    相关资源
    最近更新 更多