RazorEngine扩展方法在模板中

时间:2012-07-18 14:02:23

标签: c# razor razorengine

我使用的是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 Parsing

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");

1 个答案:

答案 0 :(得分:4)

您遇到的问题是您尝试执行方法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上使用扩展方法的类型安全方式。