如何将 Mediatr 添加到 DryIoc

How to add Mediatr to DryIoc

我目前正在尝试移植 Mediatr 管道 (Mediatr 7.0.0) 实现以使用 DryIoc Container (v. 4.0.5)。我使用了 DryIoC 版本 3.0.2 中的以下实现:

private static void ConfigureMediatr(this Container container)
{
    container.RegisterDelegate<ServiceFactory>(r => r.Resolve);
    container.RegisterMany(new[] { typeof(IMediator).GetAssembly()}, Registrator.Interfaces);
    container.RegisterMany(typeof(CopyManualsHandler).GetAssembly().GetTypes().Where(t => t.IsMediatorHandler())); //Use this to only Get Mediator Handlers.

    container.Register(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>), ifAlreadyRegistered: IfAlreadyRegistered.AppendNewImplementation);
    container.Register(typeof(IPipelineBehavior<,>), typeof(RequestPostProcessorBehavior<,>), ifAlreadyRegistered: IfAlreadyRegistered.AppendNewImplementation);
} 

实现在 3.0.2 上运行良好,我的管道似乎也很好(如果我只是将 nuget 包从 4.0.5 更改为 3.0.2,一切正常)。但是在 4.0.5 我收到异常:

System.TypeInitializationException
  HResult=0x80131534
  Message=The type initializer for 'DryIoc.OpenGenericTypeKey' threw an exception.
  Source=Program.Manuals
  StackTrace:
   at DryIoc.OpenGenericTypeKey..ctor(Type requiredServiceType, Object serviceKey) in Container.cs:line 2255
   at DryIoc.WrappersSupport.<>c__DisplayClass12_0.<GetArrayExpression>b__6(KV`2 f) in Container.cs:line 3656
   at ImTools.ArrayTools.Map[T,R](T[] source, Func`2 map) in ImTools.cs:line 569
   at ImTools.ArrayTools.Map[T,R](IEnumerable`1 source, Func`2 map) in ImTools.cs:line 605
   at DryIoc.WrappersSupport.GetArrayExpression(Request request) in Container.cs:line 3655
   at DryIoc.ExpressionFactory.CreateExpressionOrDefault(Request request) in Container.cs:line 9062
   at DryIoc.Factory.GetExpressionOrDefault(Request request) in Container.cs:line 7865
   at DryIoc.Container.ResolveAndCacheFactoryDelegate(Type serviceType, IfUnresolved ifUnresolved) in Container.cs:line 269
   at DryIoc.Container.DryIoc.IResolver.Resolve(Type serviceType, IfUnresolved ifUnresolved) in Container.cs:line 230
   at DryIoc.Resolver.Resolve(IResolver resolver, Type serviceType) in Container.cs:line 5880
   at MediatR.ServiceFactoryExtensions.GetInstances[T](ServiceFactory factory)
   at MediatR.Internal.RequestHandlerWrapperImpl`2.Handle(IRequest`1 request, CancellationToken cancellationToken, ServiceFactory serviceFactory)
   at MediatR.Mediator.Send[TResponse](IRequest`1 request, CancellationToken cancellationToken)
   at GOM.PCMF.Manuals.ViewModels.ButtonViewModel.<Copy>d__20.MoveNext() in ButtonViewModel.cs:line 76
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<>c.<ThrowAsync>b__6_0(Object state) in f:\dd\ndp\clr\src\BCL\system\runtime\compilerservices\AsyncMethodBuilder.cs:line 1018
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) in f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs:line 954
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) in f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs:line 901
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) in f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs:line 890
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at Program.Manuals.App.Main()

Inner Exception 1:
ContainerException: Unable to find a single constructor in Type OpenGenericTypeKey (including non-public=False)

(删除了 Stacktrace 中某些项目的完整文件路径。但是没有 DryIoC class 被编辑,因此行号应该是正确的)。

我尝试使用 this DryIoC example 解决问题。 然而,这对我不起作用,因为 Container 试图让许多 Types 注册。这就是为什么我切换到这一行: container.RegisterMany(typeof(CopyManualsHandler).GetAssembly().GetTypes().Where(t => t.IsMediatorHandler()));

它利用此方法查找所有 RequestHandlers:

public static bool IsMediatorHandler(this Type arg)
        {
            return arg.GetInterfaces()
                .Where(i => i.Name.StartsWith("IRequestHandler"))
                .Any();
        }

现在的问题:我在注册类型时做错了什么吗?或者这可能是来自 DryIoc 的错误?

您正在使用 DryIoc 源代码包并同时注册其 public 类型。

您需要在 RegisterMany 调用中过滤掉 DryIoc 命名空间,或者使用 DryIoc.InternalDryIoc.dll 个包。