【问题标题】:RazorEngine extension methods in a template模板中的 RazorEngine 扩展方法
【发布时间】:2012-07-18 14:02:23
【问题描述】:

我正在使用 Razor 引擎:https://github.com/Antaris/RazorEngine

我正在动态创建模型。我试图在模板中包含一个扩展方法,但它可以识别扩展类。我收到以下错误消息“'string'不包含'ToUpperFirstLetter'的定义

模型创建

dynamic model = new ExpandoObject();
((IDictionary<string, object>)model).Add("Forename", "john");

模板

@using Namespace.Extensions
@{
     ViewBag.Title = "Title";
}

Hello @Model.Forename.ToUpperFirstLetter()

扩展类

namespace Namespace.Extensions
{
    public static class StringExtensions
    {
         public static string ToUpperFirstLetter(this string source)
         {
             return ....removed for abbreviation
         }
    }
}

Razor 解析

ITemplate template = Razor.Resolve(template, model);
string result = template.Run(new ExecuteContext());

编辑

我还想在 Dynamic ExpandoObject 上创建一个扩展方法。查看模型中的值是否存在。我收到以下错误消息“System.Dynamic.ExpandoObject'不包含'HasValue'的定义

扩展类

public static class ExpandoObjectExtensions
{
    public static bool HasValue(this ExpandoObject source, string key)
    {
        return ((IDictionary<String, object>)source).ContainsKey(key);
    }
}

扩展使用

@if(Model.HasValue("Hello"))
{ 
    @Model.Hello
}

编辑两个

以下工作并进入扩展方法

var o = new object();
var bool = o.HasValue("value");

动态模型仍然抛出异常 - RuntimeBinderException: 'System.Dynamic.ExpandoObject' 不包含 'HasValue' 的定义

dynamic model = new ExpandoObject();
var bool = model.HasValue("value");

【问题讨论】:

    标签: c# razor razorengine


    【解决方案1】:

    您看到的问题是您尝试执行方法ToUpperFirstLetter(this string source),而实际上Forename 属性是dynamic。我想如果你做了类似的事情:

    @(((string)Model.Forename).ToUpperFirstLetter())
    

    ...它可能会工作。这完全取决于dynamic 的使用。动态是在运行时通过后期绑定处理的,但由于 RazorEngine 正在编译您的视图,它会尝试静态链接需要您提供动态字符串的方法。编译器不知道Forename 是一个字符串。

    您也不能dynamic 作为扩展方法的第一个参数,例如:

    public static string ToUpperFirsLetter(this dynamic source) { ... }
    

    因为扩展方法在编译时被解析为显式方法调用,但编译器不知道如何处理扩展方法中的动态第一个参数。

    编辑 根据您的回复,如果您想实现这种类型可能是动态的扩展方法,您最好使用object 并测试类型,例如:

    public static class StringExtensions
    {
      public static string ToUpperFirstLetter(this object val)
      {
        string str = val as string;
        if (string.IsNullOrWhitespace(str)) return str;
    
        return str.Substring(0, 1).ToUpper() + str.Substring(1);
      }
    }
    
    public static class ExpandoObjectExtensions
    {
      public static bool HasValue(this object val, string key)
      {
        var expando = val as ExpandoObject;
        if (expando == null) return false;
    
        return ((IDictionary<string, object>)expando).ContainsKey(key);
      }
    }
    

    ... 不理想,但它仍然是在dynamic 上使用扩展方法的一种类型安全的方式。

    【讨论】:

    • 感谢您的回复。我还想在 ExpandoObject 上提供一个扩展方法,以查看 Model 是否包含值。有没有比上面描述的更简单的方法来实现这一点?见上面的编辑
    • 您遇到了同样的问题,但请参阅编辑以获取替代解决方案。
    • 它仍然无法在动态对象上找到扩展方法。见更新。谢谢
    • 嗯,我越来越不相信扩展方法和dynamic。您可能只能将其称为ExpandoObjectExtensions.HasValue(value, key)
    • 是的,看来你是对的。动态对象无法使用扩展方法,解决方案是使用静态方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-24
    相关资源
    最近更新 更多