我遇到一个问题,即我创建的ASP.NET MVC html帮助器方法在每次调用时都不会“重新生成”。
helper方法的目的是创建要在angularjs框架中使用的Javascript对象。例如,这是一个使用helper方法的代码片段(从html页面的script标签内调用):
var app = angular.module( "appName", ["ui.bootstrap"] );
app.controller( 'appCtrl', function( $scope ) {
$scope.model = @Html.ToJavascript( Model, new string[] { "FirstName", "LastName", "ID", "Role" } );
} );
Model是具有各种属性的类的实例,但我只希望将FirstName,LastName,ID和Role序列化为javascript对象。
Statis类中定义了ToJavascript()帮助器方法,如下所示:
public static HtmlString ToJavascript( this HtmlHelper helper, object toConvert, string[] includedFields = null, Formatting formatting = Formatting.Indented, ReferenceLoopHandling loopHandling = ReferenceLoopHandling.Ignore )
{
using( var stringWriter = new StringWriter() )
using( var jsonWriter = new JsonTextWriter( stringWriter ) )
{
var serializer = new JsonSerializer()
{
// Let's use camelCasing as is common practice in JavaScript
ContractResolver = new SpecificFieldsResolver( includedFields ),
Formatting = formatting,
ReferenceLoopHandling = loopHandling,
};
// We don't want quotes around object names
jsonWriter.QuoteName = false;
serializer.Serialize( jsonWriter, toConvert );
return new HtmlString( stringWriter.ToString() );
}
}
这利用Json.NET进行实际的序列化。
Json.NET的许多很酷的功能之一是它允许您即时定义要序列化的字段。那就是SpecificFieldsResolver所做的。我将其定义如下:
public class SpecificFieldsResolver : CamelCasePropertyNamesContractResolver
{
private string[] _included;
public SpecificFieldsResolver( string[] included )
{
_included = included;
}
protected override JsonProperty CreateProperty( MemberInfo member, MemberSerialization memberSerialization )
{
JsonProperty prop = base.CreateProperty( member, memberSerialization );
bool inclField = ( _included == null )
|| _included.Contains( member.Name, StringComparer.CurrentCultureIgnoreCase );
prop.ShouldSerialize = obj => inclField;
return prop;
}
}
让我感到困惑的是CreateProperty()的调用方式。具体来说,对于要序列化的每种类型的对象,似乎只调用一次。
这是一个问题,因为在另一个cshtml文件中,我再次调用ToJavascript(),它试图序列化相同类型的对象,但是要从序列化中输出不同的字段:
var app = angular.module( "app2Name", ["ui.bootstrap"] );
app.controller( 'app2Ctrl', function( $scope ) {
$scope.model = @Html.ToJavascript( Model, new string[] { "FirstName", "LastName", "ID", "Role", "Category", "VoterID" } );
} );
Category和VoterID也是有效的类字段。但是ToJavascript()不会将它们序列化。相反,它只会序列化在第一次调用ToJavascript()中定义的字段…即使该调用发生在另一个cshtml文件中。就像SpecificFieldsResolver记住它创建的JsonProperty对象一样。
有什么想法吗?
更新资料
感谢dbc诊断确切的错误并提出解决方法。之所以略加适应,是因为我在几个解析器中依赖于Json.NET的驼峰案例名称解析:
public class CamelCaseNameMapper : CamelCasePropertyNamesContractResolver
{
public string ToCamelCase( string propertyName )
{
return ResolvePropertyName( propertyName );
}
}
public class MaoDefaultContractResolver : DefaultContractResolver
{
private CamelCaseNameMapper _mapper = new CamelCaseNameMapper();
protected override string ResolvePropertyName( string propertyName )
{
return _mapper.ToCamelCase( propertyName );
}
}
现在,从MaoDefaultContractResolver派生的每个解析器(例如我的SpecificFieldsResolver)都会自动继承驼峰式大小写,但避免了dbc标识的缓存问题。
这似乎是的错误CamelCasePropertyNamesContractResolver
。它的基类DefaultContractResolver
拥有两个构造函数:无参数构造函数和DefaultContractResolver (Boolean)
版本(在Json.NET
7.0中已作废)。该参数含义如下:
shareCache
- 类型:System.Boolean
如果设置为true,
DefaultContractResolver
将使用与相同类型的其他解析程序共享的缓存。共享缓存将显着提高多个解析器实例的性能,因为昂贵的反射将仅发生一次。如果假定解析程序的不同实例产生不同的结果,则此设置可能导致意外的行为。设置为false时,强烈建议使用重复使用DefaultContractResolver
实例JsonSerializer
。
默认值为false
。
不幸的是,默认构造函数用于CamelCasePropertyNamesContractResolver
将值设置为
true
:
public class CamelCasePropertyNamesContractResolver : DefaultContractResolver
{
public CamelCasePropertyNamesContractResolver()
#pragma warning disable 612,618
: base(true)
#pragma warning restore 612,618
{
NamingStrategy = new CamelCaseNamingStrategy
{
ProcessDictionaryKeys = true,
OverrideSpecifiedNames = true
};
}
}
此外,没有第二个带有该shareCache
选项的构造函数。这打断了你的SpecificFieldsResolver
。
解决方法是,您可以从解析器派生DefaultContractResolver
并用于CamelCaseNamingStrategy
进行名称映射:
public class IndependentCamelCasePropertyNamesContractResolver : DefaultContractResolver
{
public IndependentCamelCasePropertyNamesContractResolver()
: base()
{
NamingStrategy = new CamelCaseNamingStrategy
{
ProcessDictionaryKeys = true,
OverrideSpecifiedNames = true
};
}
}
public class SpecificFieldsResolver : IndependentCamelCasePropertyNamesContractResolver
{
// Remainder unchanged
}
请注意,如果您使用的是9.0之前的Json.NET版本,CamelCaseNamingStrategy
则不存在。而是CamelCasePropertyNamesContractResolver
可以使用嵌套的kludge
来映射名称:
public class IndependentCamelCasePropertyNamesContractResolver : DefaultContractResolver
{
class CamelCaseNameMapper : CamelCasePropertyNamesContractResolver
{
// Purely to make the protected method public.
public string ToCamelCase(string propertyName)
{
return ResolvePropertyName(propertyName);
}
}
readonly CamelCaseNameMapper nameMapper = new CamelCaseNameMapper();
protected override string ResolvePropertyName(string propertyName)
{
return nameMapper.ToCamelCase(propertyName);
}
}
问题内容: 我有以前具有大量方法的类,因此我将此方法的工作细分为“辅助”方法。 这些辅助方法声明为强制执行封装- 但是我想对大型公共方法进行单元测试。是否也可以对辅助方法进行单元测试,好象其中的一个失败,而调用它的公共方法也会失败,这样我们就可以确定为什么失败了? 另外,为了使用模拟对象测试这些对象,我需要将其可见性从私有更改为受保护,这是否可取? 问题答案: 一种方法是省略测试并将其放在同一程序
英文原文: http://emberjs.com/guides/templates/writing-helpers/ 有时,你想在程序里多次使用同一段 HTML 代码。这种情况下,你就可以自定义一个任何 Handlebars 模板都能调用的助手方法。 比如,你频繁地用一个拥有 class(译注:这个class为css中的class,非JavaScript中的类) 的 <span>来包裹特定的值。你
问题内容: 我正在尝试实现UITableViewDataSource的必需方法,但出现一个奇怪的错误: “无效的’tableview(_:cellForRowAtIndexPath :)重新声明’” 但是我不确定是什么问题。这是相关的两行代码,即类的声明和符合协议/超类的代码: 以及触发错误的函数声明: 问题答案: 您在课堂上有两次此功能。搜索它并删除其中之一。
本文向大家介绍易语言API助手使用方法,包括了易语言API助手使用方法的使用技巧和注意事项,需要的朋友参考一下 易语言API助手它的唯一功能就是方便查询API函数命令,能够自动在程序中加入指定dll命令声明的向导程序。 1、先了解一下API,Application Programming Interface,应用程序编程接口,编程人员通过这个接口,可以调用系统某些软件或者硬件的功能! 2、易语言的
我正在尝试编写一个LWRP,其中基于条件它将从助手库调用方法。我在让提供者读取外部方法时遇到语法问题。 供应商很直接 以及helper库 但每当我尝试运行它时,不管设置了什么资源属性,我都会得到 我显然在写助手库的留档中遗漏了一些东西,但我不确定是什么。试着移动一些东西,但开始没有想法。
最新版为V3.2 设计理由:Ubuntu11.10下没有合适的农历生日提醒软件。 设计思路:将农历和公历都转化为下一个公历生日,然后排序,判断在某一范围内的生日信息。 描 述:生日小助手是一款基于Tkinter,由Python编写的跨平台生日提醒软件。支持各种常见的操作系统,界面干净,操作方便,内置快捷键,可以实现 纯键盘录入,提高批量录入的效率。支持多国语言,目前支持简体中文、英语、日语