如何在ASP.NET MVC中提供自己的ICustomTypeDescriptor?

时间:2011-04-20 07:50:32

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

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

  1. 脚手架
  2. 验证
  3. Modelbinding
  4. 似乎可以通过将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只能覆盖一行或两行代码。所以它有效,但它是一个非常混乱的黑客,并可能在下次更新到新的ASP.NET MVC版本时中断。

    所以这就是我想知道的事情:我是否想念任何简单的方法?

    奖金问题:如果没有,并且您来自MVC团队,您能否考虑在MVC 4中创建适当的扩展点; - )?

    编辑:回答问题为什么我需要编写自己的TypeDescriptor代码:有几个原因:   1.最重要的是:我需要针对https://forums.asp.net/t/1614439.aspx/1中描述的问题采取解决方法   另外,我需要动态插入元数据,原因有很多。例如,我想编写自己的Bind属性,但BindAttribute是密封的。因此,在检测我自己的绑定属性实现时,我会从TypeDescriptor动态地发出匹配的BindAttribute,而不是从它派生。

2 个答案:

答案 0 :(得分:1)

根据Brad Wilson(一个ASP.NET MVC团队成员),这个问题已经被放在了MVC 4的bug列表中。所以目前似乎没有好的解决方案,但希望这会被解决当MVC 4出来时。

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

答案 1 :(得分:0)

我不确定您尝试使用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实现和Scaffolding问题。 如果我正确地假设不想用自己的元数据创建如此多的ViewModel,那么是什么导致您尝试查找自定义BindAttribute,自定义Scaffolding,自定义ModelMetadata,自定义验证和自定义ModelBinding的实现...它可能是值得的看看创建ViewModel实际需要多长时间。

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