1

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
         }
    }
}

かみそりの解析

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
}

編集 2

以下は機能し、拡張メソッドに入ります

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

動的モデルは依然として例外をスローします - RuntimeBinderException: 'System.Dynamic.ExpandoObject' には 'HasValue' の定義が含まれていません

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

1 に答える 1

4

あなたが見ている問題はToUpperFirstLetter(this string source)、実際にはForenameプロパティがであるときにメソッドを実行しようとしていることですdynamic。あなたが次のようなことをしたとしたら、私は想像します:

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

...それはおそらくうまくいくでしょう。これはすべて の使用にかかっていますdynamic。動的は遅延バインディングによって実行時に処理されますが、RazorEngine がビューをコンパイルしているとき、動的を提供している文字列を期待するメソッドを静的にリンクしようとしています。コンパイラはそれが文字列であることを知りませんForename

また、拡張メソッドに最初の引数を指定することもできません。たとえば、次のようになります。dynamic

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

拡張メソッドはコンパイル時に明示的なメソッド呼び出しに解決されますが、コンパイラは拡張メソッドの動的な最初の引数を処理する方法を認識していないためです。

EDIT あなたの応答に基づいて、動的がタイプである可能性があるこれらの種類の拡張メソッドを実現したい場合は、タイプを使用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

于 2012-07-31T10:40:54.477 に答える