CefSharp中如何转换传入.NET的JavaScript对象属性名?
问题场景
我通过CefSharp将.NET类暴露给JavaScript调用,.NET代码采用PascalCase命名规范:
public class Transformer { public Rect Rotate(Rect rect) => new Rect { Width = rect.Height, Height = rect.Width }; } public class Rect { public int Width { get; set; } public int Height { get; set; } }
为了在JavaScript中使用camelCase命名调用,我注册时配置了CamelCaseJavascriptNameConverter:
chromiumWebBrowser.JavascriptObjectRepository.NameConverter = new CamelCaseJavascriptNameConverter(); Transformer transformer = new(); chromiumWebBrowser.JavascriptObjectRepository.Register(nameof(transformer), transformer, BindingOptions.DefaultBinder);
但实际调用时,传入camelCase格式的对象无法正确绑定到.NET属性,输出结果为rect: 0×0:
await cefSharp.bindObjectAsync("transformer"); let rect = await transformer.rotate({ width: 4, height: 6 }); console.log(`rect: ${rect.width}×${rect.height}`);
排查后确认:当前NameConverter仅处理两个方向的命名转换
- 注册.NET对象时转换方法名
- .NET方法返回对象传递到JavaScript时转换属性名
不支持JavaScript传入对象到.NET时的属性名转换,我不想修改JavaScript参数为PascalCase,也不想改动.NET属性的命名风格,有没有原生解决方案?还是需要向CefSharp提交功能请求?
可行解决方案
自定义绑定器实现双向驼峰转换
可以通过自定义IBinder覆盖参数绑定逻辑,在JavaScript对象映射到.NET对象时,手动处理camelCase到PascalCase的转换。
示例代码如下:
public class CamelCaseBinder : DefaultBinder { protected override object ConvertToParameterType(object value, Type targetType, IDictionary<string, object> parameters, bool isAsync) { if (value is IDictionary<string, object> jsObject && targetType.IsClass && targetType != typeof(string)) { var instance = Activator.CreateInstance(targetType); foreach (var prop in targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { // 将JS的camelCase转为.NET的PascalCase var camelCaseName = char.ToLowerInvariant(prop.Name[0]) + prop.Name.Substring(1); if (jsObject.TryGetValue(camelCaseName, out var jsValue)) { var convertedValue = Convert.ChangeType(jsValue, prop.PropertyType); prop.SetValue(instance, convertedValue); } } return instance; } return base.ConvertToParameterType(value, targetType, parameters, isAsync); } }
注册对象时指定该自定义绑定器:
chromiumWebBrowser.JavascriptObjectRepository.Register(nameof(transformer), transformer, new BindingOptions { Binder = new CamelCaseBinder() });
此时JavaScript传入{ width:4, height:6 }时,自定义绑定器会自动将属性名转换为Width和Height,正确映射到.NET的Rect对象。
验证效果
运行原JavaScript代码,将得到正确输出:
rect: 6×4
结论
目前CefSharp原生的CamelCaseJavascriptNameConverter确实不支持JavaScript到.NET方向的属性名转换,通过自定义绑定器可以实现需求,无需修改原有代码风格。如果希望该功能成为原生支持特性,可以考虑向CefSharp提交功能请求。
内容的提问来源于stack exchange,提问作者Stefan Podskubka

