C# Cefsharp 如何利用[Attribute]的把C#中的方法给到浏览器中调用
背景
"有没有遇见这样一个场景,需要注入到浏览器的类太多,又想统一管理且不遗漏,有没有什么好办法?"
”有有有,把头伸过来~“
解决办法
第一步:提供一个[Attribute]
既然要知道哪些类需要被浏览器,那么可以使用[Attribute]进行标记。
首先我们提供一个[Attribute],
第一个原因是 考虑到cefsharp是不支持同一个类名注入的,所以使用[Attribute]也能方便取名,以便于防止重名事情发生。
其次,如果不想要注入,可以直接移除[Attribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class JSBridgeAttribute : Attribute { /// <summary> /// js中服务名称 /// </summary> public string Name { get; set; } /// <summary> /// /// </summary> public bool IsAsync { get; set; } = true; public JSBridgeAttribute() { } public JSBridgeAttribute(string name, bool isAsync = true) { this.Name = name; this.IsAsync = isAsync; } }
有了这个,可以在你想要的class上进行标记,这样就表示,存在一个 FooService,可以调用里面的方法sum
[JSBridgeAttribute("FooService")] public class Foo { public int sum(int x,int y) { return x + y; } }
第二步:在浏览器里面加入标记JSBridge类
因为要找到全部的标记JSBridge类,可以通过程序集反射得到,(考虑到这个过程耗时,要得到所有的类都加载完毕再打开浏览器,因此加上_initDll.Wait()
注意:存在某种情况找不到程序集,可能因为该程序集并没有在主程序中有过调用
/// <summary> /// 扩展全局注入js /// </summary> public static class BrowserExtend { private static readonly List<Type> TypeCache = new List<Type>(); private static Task _initDll; /// <summary> /// 初始化所有的DLL带JSBridgeAttribute的类 /// </summary> public static Task InitDllTask() { _initDll = Task.Run(()=> { var list = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in list) { foreach (var type in GetTypesWithHelpAttribute(assembly)) { TypeCache.Add(type); } } }); return _initDll; } public static void InjectBridgeObject(this BaseBrowser baseBrowser) { _initDll.Wait(); foreach (var type in TypeCache) { var item = Activator.CreateInstance(type); var attribute = item.GetType().GetCustomAttributes(typeof(JSBridgeAttribute), false).FirstOrDefault() as JSBridgeAttribute; string name = item.GetType().Name; if (attribute != null) { name = attribute.Name; } baseBrowser.RegisterJsObject(name, item, true); } } private static IEnumerable<Type> GetTypesWithHelpAttribute(Assembly assembly) { foreach (Type type in assembly.GetTypes()) { if (type.GetCustomAttributes(typeof(JSBridgeAttribute), true).Length > 0) { yield return type; } } } }
最后,在App.xaml.cs或者其他地方,使用 BrowserExtend.InitDllTask();