【问题标题】:How can I provide my own ICustomTypeDescriptor in ASP.NET MVC?如何在 ASP.NET MVC 中提供我自己的 ICustomTypeDescriptor?
【发布时间】:2019-03-04 00:31:28
【问题描述】:

我正在为 ASP.NET MVC 3 开发一个小型库,该库应该提供更好的模型元数据可重用性以及从数据实体到自定义视图模型的轻松映射。为此,我需要能够为 ASP.NET MVC 的三个不同领域提供我自己的 ICustomTypeDescriptor 实现:

  1. 脚手架
  2. 验证
  3. 模型绑定

这似乎可以通过将System.Web.Mvc.ModelMetadataProviders.Current 设置为我自己的CustomMetaDataProvider 来完成,但这还不足以涵盖以上所有三点。

问题在于 System.Web.Mvc 中有几个类直接调用到这个不可扩展的 System.Web.TypeDescriptorHelper,因为它看起来像这样:

internal static class TypeDescriptorHelper {
        public static ICustomTypeDescriptor Get(Type type) {
            return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type);
        }
    } 

我发现的唯一解决方案非常笨拙,需要从 System.Web.Mvc 子类化许多类型才能使其工作。我什至不得不完全重新实现CustomModelBinderDictionary,只是为了覆盖一两行代码。所以它可以工作,但它是一个非常混乱的 hack,并且可能会在我下次更新到新的 ASP.NET MVC 版本时中断。

以下是我想了解的内容:我错过了任何简单的方法吗?

额外问题:如果不是,并且您来自 MVC 团队,您是否可以考虑在 MVC 4 中创建一个适当的可扩展点 ;-)?

编辑: 回答为什么我需要编写自己的 TypeDescriptor 的问题:这有几个原因: 1. 最重要的是:我需要解决https://forums.asp.net/t/1614439.aspx/1 中描述的问题 2.另外,由于各种原因,我需要动态插入元数据。例如,我想编写自己的 Bind 属性,但 BindAttribute 是密封的。因此,当检测到我自己的绑定属性实现时,我不是从它派生,而是从 TypeDescriptor 动态发出匹配的 BindAttribute。

【问题讨论】:

    标签: asp.net-mvc validation modelbinders scaffolding modelmetadata


    【解决方案1】:

    Brad Wilson(一名 ASP.NET MVC 团队成员)称,此问题已被列入 MVC 4 的错误列表。所以目前似乎没有好的解决方案,但希望在 MVC 时能解决这个问题4出来。

    任何对我的可重用验证和脚手架元数据和模型/视图模型映射库感兴趣的人,请随时订阅我的博客https://devermind.wordpress.com/。我要在那里释放图书馆。

    【讨论】:

    • 嗨。似乎指向您网站的链接不起作用。我目前面临同样的问题,想知道这是否不能通过创建一个指向元数据来源类型的自定义代理属性更简单地完成。然后实现一个 CustomDataAnnotationsModelMetadataProvider,覆盖 CreateMetadata(),它将在调用基之前扩展代理属性以补充属性列表。你认为这行得通吗?
    • @ricardo:让 ASP.NET MVC 始终如一地使用您的 CustomDataAnnotationsModelMetadataProvider 的问题。不幸的是,ASP.NET MVC 3 没有提供单一一致的可扩展点,可以覆盖以修补您的 CustomDataAnnotationsModelMetadataProvider。相反,它会在各种地方创建默认的 DataAnnotationsModelMetadataProvider 实现。可以覆盖所有这些,但只能以一种相当混乱和相当复杂的方式完成。经过几个小时的反复试验和分析 ASP.NET MVC 源代码,我才设法做到了。
    • 是否有可能看到您对此的解决方案。我似乎无法访问您的网站。起来了吗?
    • 里卡多:不,抱歉。我目前正在切换到另一个博客提供商。反正我还没有写过关于这个的博客文章。如果需要,我可以通过电子邮件发送给您。
    • 那太好了,谢谢。我的地址是 ricardods(at)sky.com
    【解决方案2】:

    我不确定您尝试使用 Validation、ModelBinding 和可能的 ModelMetadata 的自定义实现来做什么,而 MVC 中的 DependencyResolver 功能无法做到这一点?

    最近的 MVC 3 工具更新中的新脚手架支持可能会满足您对脚手架的需求;但是,我会看一下是否可以连接到 ModelBinding、ModelMetadata 和 Validation 的 DependencyResolver 功能,看看它们是否可以实现您正在寻找的东西。我最近遇到了类似的情况,我需要从头开始实现很多这些行为以提供一个灵活的框架,而我只需使用 IoC 的 ModelMetadata 和 Validation 提供程序就可以做到这一点。我还最终在少数情况下继承了 DynamicObject(或 ExpandoObject)以提供更大的灵活性。我知道这不是一个直接的答案,但我不确定您为什么需要访问低于这些可扩展性点的任何东西?

    编辑:如果您希望在类似的 ViewModel 上重用 ModelMetadata 以避免在多个地方重新定义相同的 ModelMetadata,您可能需要考虑这一点的含义。很多时候,您希望对实体进行某些数据限制,但这些限制应该在 DataModel 而不是 ViewModel 上。用户可能有稍微严格的规则。例如,您可以规定某些字段对于 ViewModel 中的用户是只读的,但用作 DataModel 的实体确实允许您修改值(通常在您的代码中)。同样,您可能会遇到用于为 VideModel 生成 Create 视图的 ModelMetadata 可能与用于 Edit 视图的 ViewModel 略有不同的情况。重用它们似乎是保持一致性和减少代码重复的好方法,但以后可能会后悔。我最近遇到了同样的问题,我想避免为每个可能导致回发的视图编写新的 ViewModel,我还没有找到我喜欢的完美解决方案,但我认为重用 ModelMetadata 会导致更多问题,它可能会解决我的意见。为需要它们的视图编写 ViewModel 也可能消除您实现自定义 BindAttribute 实现和脚手架问题的需要。 如果我假设不想用自己的元数据创建这么多 ViewModel 是正确的,那么这就是导致您尝试查找自定义 BindAttribute、自定义脚手架、自定义 ModelMetadata、自定义验证和自定义 ModelBinding 的实现的原因......它可能值得查看创建 ViewModel 实际需要多少时间。

    如果您找到更好的方法,请随时告诉我 :-)

    【讨论】:

    • 请看我上面的编辑。不幸的是,我没有看到 DependencyResolver 如何帮助我完成编辑中的第 1 点……如果你能证明我错了,我会很高兴 :-)
    • 关于您的编辑:我已经完成了我的库,我认为它很好地解决了您描述的问题:它允许您重用任何元数据应该与您的数据实体中保持相同,但覆盖有什么不同。这正是我实现自己的 TypeDescriptor 所需要的。在我在当前的生产项目中获得更多使用它的经验后,我将发布该库。如果您有兴趣,请随时在 devermind.com 上订阅我的博客。
    猜你喜欢
    • 1970-01-01
    • 2014-03-15
    • 2019-09-30
    • 2021-10-31
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多