2010-11-12 56 views
7

我正在创建一个MVC-应用程序,它目前使用EditorFor来生成许多视图。整个视图基本上只是一个EditorForModel,而且效果很好。然而,我遇到了一个小问题,我似乎找不到解决方案,并且按照我需要的方式工作非常重要,也就是在尝试渲染EditorFor一个接口时。绑定和类似的东西都已经被处理了,但问题是EditorFor看到它是一个接口,并且默认为“Object”模板。我需要它来查看接口并查看它是否可以找到具有该名称的模板,如果不能,我需要它查看当前存在的所有接口以查看它是否匹配其中的任何接口。为了简单地解释一下这个例子:覆盖ASP.NET MVC 3中的默认EditorFor模板选择RC

接口:

public interface IAppProvider 
{ 
    string Name { get; set; } 
} 

public interface IAppMusicProvider : IAppProvider 
{ 
    int GetPlaylistCount(); 
} // Yeah, I know, this interface is not smart, but it's only for show. 

如果我现在创建一个模型=“IAppMusicProvider”视图,并运行Html.EditorForModel(),我需要它来找到“〜意见\共享\ EditorTemplates \ IAppProvider.cshtml“-template。有什么简单的方法可以实现这一目标吗?

回答

1

您是否尝试过使用[TemplateHint]属性?

+0

呀,这样的作品,但它不是解决问题的方式(或者更确切地说,我用实际上是[DataType]属性)。我正在制作的应用程序将运行插件,我只需要通过设置接口来工作,而不必强制所有插件开发人员使用用户[DataType(“IAppProvider”)]''。 – Alxandr 2010-11-12 02:56:47

+0

尝试命名与界面相同的模板?如果我记得那是唯一的两个选择。 – jfar 2010-11-12 03:11:04

+0

这也不起作用,因为模板需要适用于所有IAppProvider。我正在寻找一些方法来覆盖这个默认行为,所以如果我提供一个IAppProvider实现接口,它将使用IAppProvider模板。这可能需要在MVC的某处进行编码(某些组件需要更改,就像您可以使用ControllerFactory等一样),但我甚至不知道从哪里开始。 – Alxandr 2010-11-12 03:16:02

1

您可以在ModelMetadataProvider中尝试更改ModelMetadata.TemplateHint。这样做的一个方法是使用Decorator模式:

public class AbstractTypeTemplateSupportingModelMetadataProvider : ModelMetadataProvider 
{ 
    private readonly ModelMetadataProvider wrapped; 

    public AbstractTypeTemplateSupportingModelMetadataProvider(ModelMetadataProvider wrapped) 
    { 
     this.wrapped = wrapped; 
    } 

    public override IEnumerable<ModelMetadata> GetMetadataForProperties(object container, Type containerType) 
    { 
     var result = this.wrapped.GetMetadataForProperties(container, containerType).ToList(); 
     result.ForEach(ChangeTemplateHint); 

     return result; 
    } 

    public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName) 
    { 
     var result = this.wrapped.GetMetadataForProperty(modelAccessor, containerType, propertyName); 
     ChangeTemplateHint(result); 

     return result; 
    } 

    public override ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType) 
    { 
     var result = this.wrapped.GetMetadataForType(modelAccessor, modelType); 
     ChangeTemplateHint(result); 

     return result; 
    } 

    private void ChangeTemplateHint(ModelMetadata source) 
    { 
     if (source.Model is IAppProvider) //Or use source.ModelType if you want to support the model being null. 
      source.TemplateHint = typeof(IAppProvider).Name; 
    } 
} 

而且在你的启动逻辑:

ModelMetadataProviders.Current = new AbstractTypeTemplateSupportingModelMetadataProvider(ModelMetadataProviders.Current);