Как добавить Mediatr в DryIoc

В настоящее время я пытаюсь портировать реализацию Mediatr Pipeline (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)

(Удален полный путь к некоторым элементам в трассировке стека. Однако класс DryIoC не редактировался, поэтому номера строк должны быть правильными).

Я попытался исправить проблему, используя этот DryIoC пример . Однако это не сработает для меня, потому что 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?


person Brezelmann    schedule 02.08.2019    source источник
comment
Вы используете пакет DryIoc или DryIoc.dll?   -  person dadhi    schedule 02.08.2019
comment
Я использую DryIoc, установленный пакетом nuget. Я получаю папку с классами DryIoc в свое приложение. В моей выходной папке нет (насколько я знаю) лишней DryIoc.dll.   -  person Brezelmann    schedule 02.08.2019
comment
Если это поможет: конвейер Mediatr и все его классы живут в библиотеке классов. Вызывающий код, создающий контейнер из DryIoc, представляет собой приложение wpf.   -  person Brezelmann    schedule 02.08.2019
comment
Попробуйте пакеты DryIoc.dll или DryIoc.Internal.   -  person dadhi    schedule 02.08.2019
comment
попробую в понедельник. Даю вам обратную связь тогда. Спасибо за помощь и изучение этого.   -  person Brezelmann    schedule 03.08.2019
comment
Попробовал это секунду назад, и использование DryIoc.dll, похоже, работает нормально (сейчас я нажимаю на свой обработчик Mediatr). Спасибо за помощь @dadhi. Не могли бы вы пояснить, почему DryIoc.dll работает, а исходный код DryIoc не работает, хотя у них один и тот же номер версии?   -  person Brezelmann    schedule 05.08.2019
comment
Дал полный ответ   -  person dadhi    schedule 05.08.2019


Ответы (1)


Вы используете исходный пакет DryIoc и также регистрируете его общедоступные типы.

Вам нужно либо отфильтровать DryIoc пространство имен в RegisterMany вызовах, либо использовать пакеты DryIoc.Internal или DryIoc.dll.

person dadhi    schedule 05.08.2019
comment
Благодарю за разъяснение. Это объясняет (по крайней мере для меня) странную ошибку в отношении типов DryIoc. - person Brezelmann; 06.08.2019
comment
Кстати, DryIoc v4 имеет свои собственные абстракции, подобные MediatR, в пространстве имен DryIoc.Messages. - person dadhi; 06.08.2019
comment
Документы DryIoc.Messages с живым примером находятся здесь: github.com/dadhi/DryIoc/blob/master/docs/DryIoc.Docs/ - person dadhi; 10.12.2020