castleproject / Core

Castle Core, including Castle DynamicProxy, Logging Services and DictionaryAdapter
http://www.castleproject.org/
Other
2.2k stars 468 forks source link

Issue using Castle with Blazor WebAssembly #589

Closed robertmclaws closed 3 years ago

robertmclaws commented 3 years ago

Hey folks! Was trying to use the super-cool ChangeTracker project in by Blazor WebAssembly app on .NET 5, and ran into this issue:

blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: The method or operation is not implemented.
System.NotImplementedException: The method or operation is not implemented.
   at System.RuntimeType.MakeGenericType(Type[] instantiation)
   at Castle.DynamicProxy.Internal.TypeUtil.GetClosedParameterType(AbstractTypeEmitter type, Type parameter)
   at Castle.DynamicProxy.Internal.TypeUtil.CloseGenericParametersIfAny(AbstractTypeEmitter emitter, Type[] arguments)
   at Castle.DynamicProxy.Internal.TypeUtil.GetClosedParameterType(AbstractTypeEmitter type, Type parameter)
   at Castle.DynamicProxy.Contributors.DelegateTypeGenerator.GetParamTypes(AbstractTypeEmitter delegate)
   at Castle.DynamicProxy.Contributors.DelegateTypeGenerator.BuildInvokeMethod(AbstractTypeEmitter delegate)
   at Castle.DynamicProxy.Contributors.DelegateTypeGenerator.Generate(ClassEmitter class, ProxyGenerationOptions options, INamingScope namingScope)
   at Castle.DynamicProxy.Contributors.ClassProxyWithTargetTargetContributor.<>c__DisplayClass7_0.<GetDelegateType>b__0(CacheKey _)
   at Castle.Core.Internal.SynchronizedDictionary`2[[Castle.DynamicProxy.Generators.CacheKey, Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc],[System.Type, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetOrAddWithoutTakingLock(CacheKey key, Func`2 valueFactory)
   at Castle.DynamicProxy.Contributors.ClassProxyWithTargetTargetContributor.GetDelegateType(MetaMethod method, ClassEmitter class, ProxyGenerationOptions options)
   at Castle.DynamicProxy.Contributors.ClassProxyWithTargetTargetContributor.IndirectlyCalledMethodGenerator(MetaMethod method, ClassEmitter proxy, ProxyGenerationOptions options, OverrideMethodDelegate overrideMethod)
   at Castle.DynamicProxy.Contributors.ClassProxyWithTargetTargetContributor.GetMethodGenerator(MetaMethod method, ClassEmitter class, ProxyGenerationOptions options, OverrideMethodDelegate overrideMethod)
   at Castle.DynamicProxy.Contributors.CompositeTypeContributor.ImplementMethod(MetaMethod method, ClassEmitter class, ProxyGenerationOptions options, OverrideMethodDelegate overrideMethod)
   at Castle.DynamicProxy.Contributors.CompositeTypeContributor.Generate(ClassEmitter class, ProxyGenerationOptions options)
   at Castle.DynamicProxy.Generators.ClassProxyWithTargetGenerator.GenerateType(String name, INamingScope namingScope)
   at Castle.DynamicProxy.Generators.BaseProxyGenerator.<>c__DisplayClass33_0.<ObtainProxyType>b__0(CacheKey _)
   at Castle.Core.Internal.SynchronizedDictionary`2[[Castle.DynamicProxy.Generators.CacheKey, Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc],[System.Type, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetOrAdd(CacheKey key, Func`2 valueFactory)
   at Castle.DynamicProxy.Generators.BaseProxyGenerator.ObtainProxyType(CacheKey cacheKey, Func`3 factory)
   at Castle.DynamicProxy.Generators.ClassProxyWithTargetGenerator.GetGeneratedType()
   at Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxyTypeWithTarget(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
   at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyTypeWithTarget(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
   at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyWithTarget(Type classToProxy, Type[] additionalInterfacesToProxy, Object target, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
   at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyWithTarget(Type classToProxy, Type[] additionalInterfacesToProxy, Object target, ProxyGenerationOptions options, IInterceptor[] interceptors)
   at ChangeTracking.ChangeTrackingFactory.AsTrackable[CompanyOffering](CompanyOffering target, ChangeStatus status, Action`1 notifyParentListItemCanceled, ChangeTrackingSettings changeTrackingSettings, Graph graph) in C:\projects\changetracking\Source\ChangeTracking\ChangeTrackingFactory.cs:line 74
   at ChangeTracking.ChangeTrackingCollectionInterceptor`1[[CloudNimble.BurnRate.Core.CompanyOffering, CloudNimble.BurnRate.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]..ctor(IList`1 target, ChangeTrackingSettings changeTrackingSettings, Graph graph) in C:\projects\changetracking\Source\ChangeTracking\ChangeTrackingCollectionInterceptor.cs:line 37
   at ChangeTracking.ChangeTrackingFactory.AsTrackableCollection[CompanyOffering](ICollection`1 target, ChangeTrackingSettings changeTrackingSettings) in C:\projects\changetracking\Source\ChangeTracking\ChangeTrackingFactory.cs:line 106
   at ChangeTracking.ChangeTrackingFactory.AsTrackableCollection[CompanyOffering](ICollection`1 target) in C:\projects\changetracking\Source\ChangeTracking\ChangeTrackingFactory.cs:line 48
   at ChangeTracking.Core.AsTrackable[CompanyOffering](IList`1 target) in C:\projects\changetracking\Source\ChangeTracking\Core.cs:line 50
   at ------------------------------------- in -------------------------------------
   at Microsoft.AspNetCore.Components.EventCallbackWorkItem.InvokeAsync[Object](MulticastDelegate delegate, Object arg)
   at Microsoft.AspNetCore.Components.EventCallbackWorkItem.InvokeAsync(Object arg)
   at Microsoft.AspNetCore.Components.ComponentBase.Microsoft.AspNetCore.Components.IHandleEvent.HandleEventAsync(EventCallbackWorkItem callback, Object arg)
   at Microsoft.AspNetCore.Components.EventCallback`1[[Microsoft.AspNetCore.Components.Forms.EditContext, Microsoft.AspNetCore.Components.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].InvokeAsync(EditContext arg)
   at Microsoft.AspNetCore.Components.Forms.EditForm.HandleSubmitAsync()
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

Can potentially provide a repro if necessary. I know they are working on System.Reflection.Emit full support in Mono for .NET 6.0, just wanted to make sure this was on your radar once that happens.

Thanks!

teneko commented 3 years ago

I was facing an similiar bug. (see https://github.com/castleproject/Core/issues/585) As of current, the fixing pull request is not yet reflected in a released version. Perhaps you would try out a package (Teronis.Castle.Core) with applied pull request?

stakx commented 3 years ago

Thanks for taking the time to report this @robertmclaws.

System.NotImplementedException: The method or operation is not implemented.
  at System.RuntimeType.MakeGenericType(Type[] instantiation)

just wanted to make sure this was on your radar once that happens

DynamicProxy very much depends on Reflection and System.Reflection.Emit. Realistically speaking, any platform/target that doesn't have full support for those facilities is essentially unsupported by DynamicProxy. There's not a whole lot that can be done about that short of a complete rewrite; depending on the exact use case, one may be better off with newer libraries that leverage compile-time code generation (e.g. those based on Roslyn code generators).

We do not keep a complete list of exactly which platforms/targets are supported by DP and which are not. Doing so would require testing setups for all possible platforms, and perhaps even dedicated testing hardware. Furthermore, that list would be subject to change as platforms and technologies evolve — we frankly don't have the resources to track them all, and have to leave it at a general statement that we support .NET Framework and .NET Core, but we probably cannot support scenarios where SRE is restricted (such as mobile platforms and AOT compiled code).

I don't think there's anything to be done here, so unless I've misunderstood the intent behind this issue, I'm going to close it in a few days' time.