Closed 2881099 closed 8 months ago
例如按照约定方法:
public class xxx
{
IServiceProvider Service; // Rougamo 内部获取这个字段或属性
[XxxMo]
public void xxx() {}
}
class XxxMo : MoAttrite
{
public override void OnEntry(MethodContext context)
{
var service = context.GetService(); //按照约定方式
}
}
class XxxMo : MoAttrite
{
public override void OnEntry(MethodContext context)
{
var prop = context.TargetType.GetProperty("ServiceProvider", BindingFlags.Public | BindingFlags.NonPublic);
if (prop == null) throw new Exception($"{context.TargetType.DisplayCsharp()} 未定义 IServiceProvider ServiceProvider {{ get; set; }}");
var service = prop.GetValue(context.Target);
}
}
已解决,谢谢。
反馈一下问题,关于泛型下 TargetType 使用 Mo 的处理:
new MethodContext(this, typeof(Xxx<>)
TargetType 使用的不是 typeof(Xxx\<int>)
感谢反馈,稍后将进行修复
回顾了一下代码,TargetType这样的表现不是bug,TargetType是编译时获取的定义的类型本身,无法得知使用时的泛型类型参数,如果需要获取包含泛型类型参数的实际类型,需要通过Target.GetType()
来获取了。需要注意的是,如果方法时静态方法,Target
为null
老哥现在对blazor ssr的IServiceProvider
的获取有没有什么好的方式。前些天封装了AspNetCore和通用主机获取IServiceProvider
,然后有人反馈希望能支持blazor,我看了下blazor的scope关系,感觉有点难整,也没有找到比较好的blazor生命周期事件进行操作。
public override void OnEntry(MethodContext context)
{
var targetType = context.Target.GetType();
var service = targetType.GetPropertyOrFieldValue(context.Target,
"ServiceProvider") as IServiceProvider;
if (service == null)
throw new Exception($"_Imports.razor 未使用 @inject IServiceProvider ServiceProvider");
}
我目前是这样处理的,前提要在 _Imports.razor 定义
https://github.com/2881099/AdminBlazor/blob/master/AdminBlazor/_Imports.razor
感谢老哥的分享。这两天看blazor源码看得头疼,感觉目前blazor还是太封闭了,在各个生命周期节点没有提供切面点,关键的类型也全是internal sealed的,甚至连注册到ServiceProvider的接口都是internal的,完全不给自定义扩展留口子
ssr ioc scoped 是整个 websocket,和传统 webapi 不一样。
嗯,不仅如此,他的scope还是穿插使用的,与websocket一对一关联scope是在创建CircuitHost
时创建的
而在界面上点击按钮时,服务端执行点击事件对应方法时又会在DefaultHubDispatcher
中再创建一个scope,这时就是两个不同scope中的对象穿插使用了
这么做其实也好理解,点击事件中产生的部分对象只需要在本次点击事件中存活,不需要关联到整个websocket生命周期。
其实他的scope怎么处理问题都不大,最大的问题就是做得太封闭,我目前知道的只有可以通过CircuitHandler
在websocket连接和断开时做额外处理,像每次界面点击的这种回调没找到相关扩展方式。
我没有研究这么深入,怕后续版本改动。
确实,这么多internal类型和接口,可能随时都会改掉内部实现,这么费力可能也只适用于当前版本
我还是用AsyncLocal
来实现的,通过重写ComponentBase
的IHandleEvent
接口方法来实现。
我现在已经针对Blazor编写了对应的肉夹馍DI扩展,可以直接引用NuGet,参考:https://github.com/inversionhourglass/Rougamo.DI/tree/master/samples/BlazorServerApp
最近接触 blazor SSR,使用 AsyncLocal 的方式存储 IServiceProvider 不再凑效了。
blazor SSR 的特点是长连接,ioc Scoped 正常使用没问题,AsyncLocal 在这种模式下很容易丢失上下文,原因是长链接各种异步 UI 操作,一言难尽。
希望肉夹馍提供与 IServiceProvider 设置有关的方式。