TypeScript InversifyJS: asynchronous binding - asynchronous

I'm facing this kind of problem: I'm creating Event Manager with ability to handle several concrete providers, and I'm struggling with dependency injection issue here.
I'm using:
Typescript#2.0.10, node#7.0.0, inversify#2.0.1, inversify-binding-decorators#2.0.0
Lets see that in code:
const socketIO: SocketIO.Server = io.listen(instance);
kernel.bind<SocketIO.Server>(TYPES.SocketIO).toConstantValue(socketIO);
const eventManager: IEventManager = kernel.get<IEventManager>(TYPES.IEventManager);
eventManager.init(kernel.getAll<IEventManagerProvider>(TYPES.IEventManagerProvider));
console.log(eventManager);
And console logs me that event manager is undefined, which crashes the whole app. But...
When I disable the kernel.getAll(...) from init, then I'm receiving just what I've expected:
const eventManager: IEventManager = kernel.get<IEventManager>(TYPES.IEventManager);
eventManager.init([]);
console.log(eventManager);
Gives me: MultipleProvidersEventManager { providers: {} }. The init method is very simple by itself and contains:
#provideSingleton(TYPES.IEventManager)
class MultipleProvidersEventManager {
...
public init(providers: IEventManagerProvider[]): void {
forEach(providers, this.registerProvider);
}
public registerProvider(provider: IEventManagerProvider): void {
if (this.providers[provider.type()]) {
throw new Error('Event Manager provider already registered');
}
console.log('Registered ' + provider.type() + ' event manager provider');
this.providers[provider.type()] = provider;
}
...
}
So my problem is that I have to wait with calling the init method until
all required objects are stored properly in InversifyJS container and can be returned. But I don't know how :(. Can someone explain me how should I solve this problem ?

Ok, I've solve it.
The problem was in totally different place that I was thinking on the beginning.
So... in MultipleProvidersEventManager class on init method, forEach was loosing the context of the caller. Adding bind soved the problem..
forEach(providers, this.registerProvider.bind(this));
... is the anwser.

Related

Why onTapEvent method of OnGestureListenerAdapter is invoked on background thread?

We are using premium SDK and OnTapEvent callback of OnGestureListenerAdapter interface is invoked on background thread. Is it intended behaviour or bug in SDK?
Tried to find answer in docs but there is no info about this behaviour.
val state = MutableLiveData<MapViewState>()
override fun onTapEvent(point: PointF): Boolean {
viewModel.onMapClick()
return false
}
fun onMapClick() {
state.setValue(state.copy(selected = None))
}
Getting error when trying to set value to LiveData directly from onTapEvent.
java.lang.IllegalStateException: Cannot invoke setValue on a background thread
at androidx.lifecycle.LiveData.assertMainThread(LiveData.java:443)
at androidx.lifecycle.LiveData.setValue(LiveData.java:286)
at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:33)
at com.example.MapFragment.onTapEvent(MapFragment.kt:121)
at com.nokia.maps.MapGestureHandlerBase.a(MapGestureHandlerBase.java:253)
at com.nokia.maps.MapGestureHandlerBase.a(MapGestureHandlerBase.java:230)
at com.nokia.maps.NmaaGestureHandler.handleTap(NmaaGestureHandler.java:230)
at com.nokia.maps.NmaaGestureHandler.pollNative(Native Method)
at com.nokia.maps.NmaaGestureHandler.a(NmaaGestureHandler.java:26)
at com.nokia.maps.NmaaGestureHandler$a.d(NmaaGestureHandler.java:379)
at com.nokia.maps.NmaaGestureHandler$a.c(NmaaGestureHandler.java:371)
at com.nokia.maps.NmaaGestureHandler$a.a(NmaaGestureHandler.java:363)
at com.nokia.maps.NmaaGestureHandler$a$1.a(NmaaGestureHandler.java:390)
at com.nokia.maps.NmaaGestureHandler$b.run(NmaaGestureHandler.java:429)
Seems logic to have this callback invoked on main thread.
Quick answer is: to avoid ANR. SDK user can write heavy code and that will cause application not responding issue.
There are two ways to solve the issue:
1) Post your actions to UI thread like below:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// customer code
}
});
2) Use asynchronous listeners, which are called on UI thread. You have to register your gesture listener using "false" value as third param:
m_mapGesture.addOnGestureListener(gestureListener, 0, false);
Hope this helps!

AutoFixture/AutoMoq: Unable to Create Instance (`BadImageFormatException`)

Below is a minimal example of the problem I am currently encountering:
using System.Net.WebSockets;
using AutoFixture;
using AutoFixture.AutoMoq;
using FluentAssertions;
using Xunit;
...
[Fact]
public void Test1()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization() { ConfigureMembers = true });
var sut = fixture.Create<WebSocket>();
sut.Should().NotBeNull();
}
[Fact]
public void Test2()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization() { ConfigureMembers = true });
var sut = new Mock<WebSocket>().Object;
fixture.Inject(sut);
sut.Should().NotBeNull();
}
...
When I run the first test, I get the following exception:
AutoFixture.ObjectCreationExceptionWithPath : AutoFixture was unable to create an instance from Moq.Mock`1[System.IO.Stream] because creation unexpectedly failed with exception. Please refer to the inner exception to investigate the root cause of the failure.
Inner exception messages:
System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
The second test succeeds.
I would like to be able to create an instance of a class using AutoFixture which takes a WebSocket as a constructor parameter, without the need to inject a mock object first (ultimately, so that I can use an AutoMoqData attribute, and get rid of some boilerplate). Have I got any misusage or misunderstanding going on here, or would this be better placed as a GitHub issue? In the interim, is there anything I can do to work around this issue?
You observe this issue because of the AutoFixture's factory discovery strategy. When you try to create an object of an abstract type, AutoFixture still inspects the type to find a static factory method to activate the object. In your particular case, the WebSocket type contains such methods, so some of them is used. It looks like it doesn't work well with auto-generated input values, so fails with an exception.
You can customize AutoFixture, to always mock the WebSocket type:
fixture.Register((Mock<WebSocket> m) => m.Object);
Just tested with the latest versions of products (AutoFixture 4.5.0, Moq 4.10.0) and it works like a charm.

Using Lazy<> with Prism.DryIoc.Forms gives "container is garbage collected" exception

We're using Prism.DryIoc.Forms to create apps with Xamarin.Forms. To minimize the startup time of the app we are using the Lazy<> pattern for classes with a lot of dependencies.
This used to work fine with Prism.Unity.Forms. However, I can't get it to work with Prism.DryIoc.Forms. Any help would be appreciated.
The code is as follows. We have a page view model like this:
public class MySamplePageViewModel
{
private readonly Lazy<ISomeClass> _lazySomeClass;
public MySamplePageViewModel(Lazy<ISomeClass> lazySomeClass)
{
_lazySomeClass = lazySomeClass;
}
public void SomeMethod()
{
_lazySomeClass.Value.DoIt(); //throws exception
}
}
However, after the page view model is being instantiated, when calling _lazySomeClass.Value we get an exception with message "Container is no longer available (has been garbage-collected).".
It seems to be related to how Prism resolves the view model, because when calling the following it works fine:
var container = (Application.Current as PrismApplicationBase<IContainer>).Container;
var lazySomeClass = container.Resolve<Lazy<ISomeClass>>();
lazySomeClass.Value.DoIt(); //works fine
we're doing the registration like this:
container.Register<ISomeClass, SomeClass>(Reuse.Singleton);
container.RegisterTypeForNavigation<MySamplePage, MySamplePageViewModel>("MySamplePage");
The problem should be fixed in v2.10.3.
Therefore the next logical step is to ask Prism.DryIoc.Forms maintainers to update to the latest DryIoc version.

MemoryCache.Default in MVC Disposing Workaround

I am having a hard-time implementing the workaround to the problem with disposing Cache mentioned in this thread MemoryCache Empty : Returns null after being set.
My latest attempt has the following code to get an instance, wrapped as suggested, in a using statement to suppress the cache from being disposed:
private static CacheDl _instance;
public static CacheDl Instance
{
get
{
if (_instance == null)
{
using (ExecutionContext.SuppressFlow())
{
_instance = new CacheDl();
}
}
return _instance;
}
}
private static ObjectCache Cache { get { return MemoryCache.Default; } }
Of course this doesn't work.. I have also tried wrapping the Cache 'getter' in something similar but still no deal.
I have also tried specifying a large pollingInterval to suppress the behavior altogether and still no success.
private ObjectCache _cache;
private ObjectCache Cache
{
get
{
using (ExecutionContext.SuppressFlow())
{
return _cache ?? (_cache = new MemoryCache("my-cache", new NameValueCollection { { "pollingInterval", "30:00:00" } }));
}
}
}
You guessed it, no luck. Any help would be greatly appreciated.
By the way, I have already requested the mentioned Fixpack from Microsoft but not yet heard anything back after 4 hours having submitted the request..
Honestly, I would really prefer that this would be rolled up into an official Windows Update so we wouldn't have to hack around to get this working on non-.NET 4.5 systems.
Update:
Specifically, I would like to know how I am meant to implement the recommended work-around. Can someone please show an example of how this can be implemented?
I am working on this same problem. In my case the problem seems to be the cache is disposed on the AppDomain's UnhandledException event. See the source snippet of MemoryCache here.
As you can see, it disposes itself. My solution is to wrap my cache access in a class that can subscribe to this event and initialize a new cache when the old one gets disposed. This solution seems to work for me but it does feel rather hack-y.
The cache will still be cleared unexpectedly on the UnhandledException event, but at least this way you are able to start over using a new cache.
public class MyCacheWrapper
{
private MemoryCache cache;
public MyCacheWrapper()
{
cache = new MemoryCache("settings");
AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
{
if(args.IsTerminating)
cache = new MemoryCache("settings");
};
}
}
Note also that you can also use this class to dispose and recreate the cache when you wish to clear it, because MemoryCache's Trim() method does not work properly.
Ended up sorting this out with configuration settings to extend the Cache polling interval sufficient enough that the application pool will recycle before the interval is reached. Had tried doing this in code when constructing a Cache instance but that didn't work out..
A comment on the relevant Connect issue mentions this as workable hack if you can control your application pool, while another mentions this on the social.msdn forum.
Connect Issue
social.msdn
The configuration setting which increases the polling interval by 30 hours:
<system.runtime.caching>
<memoryCache>
<namedCaches>
<add name="Default"
cacheMemoryLimitMegabytes="0"
physicalMemoryLimitPercentage="0"
pollingInterval="30:00:00" />
</namedCaches>
</memoryCache>
</system.runtime.caching>

Event not working

I am new to Tridion Event System. I have written a small code.
[TcmExtension("MyEventHandlerExtension")]
public class EH : TcmExtension
{
public EH()
{
Subscribe();
}
public void Subscribe()
{
//EventSystem.Subscribe<Component, DeleteEventArgs>(HandlerForInitiated, EventPhases.Initiated);
EventSystem.Subscribe<Tridion.ContentManager.CommunicationManagement.Page, Tridion.ContentManager.Extensibility.Events.PublishOrUnPublishEventArgs>(HandlerForCommitted, EventPhases.All);
}
private void HandlerForCommitted(IdentifiableObject subject, PublishOrUnPublishEventArgs args, EventPhases phase)
{
TDSE obj = new TDSE();
Tridion.ContentManager.Interop.TDS.Publication pub = obj.GetPublication("tcm:0-150-1");
Tridion.ContentManager.Interop.TDS.Page pubPage = obj.GetPage("tcm:150-12374-64", pub);
pubPage.Publish("tcm:0-1-65538", false, true, false, default(DateTime), default(DateTime), default(DateTime));
}
}
using this code i wanted to publish a page everytime when a publish and unpublish event occur.
I build this code and register its path in tridion config file .
But its not working.Please Help
Ok, first of all remove all your TDSE code, you should use TOM.NET. You can get session as subject.Session
Then make sure you have registered this extension in Tridion.ContentManager.config and restarted your system
And finally - if something doesn't work, just add simple code that will create a file in your HandlerForCommitted whenever event occurs, this way you will be able to see if your extension get executed.
The 2011 Event System uses the TOM.NET API and not the TOM API. Please do not create new TDSE objects in the 2011 Event System. Even though you can reference the old Interop libraries, there is no reason to do so with 2011. Using the TOM.NET libraries you should see better performance and also the code is future-proof.
Mihai Cadariu has a nice example where he uses TOM.NET to Publish a page from a Tridion Template. Adjusting the code to check for previewmode or publish mode and setting your own user and priority (instead of reading it from the current transaction) should work well.
Below code from http://yatb.mitza.net/2012/05/publishing-from-template-code-using.html
public void Publish(Engine engine, String tcmUri, User user, PublishPriority priority)
{
Session session = new Session(user.Title);
PublishInstruction publishInstruction = new PublishInstruction(session);
RenderInstruction renderInstruction = new RenderInstruction(session);
renderInstruction.RenderMode = RenderMode.Publish; // work around. needs to be specified for binaries.
publishInstruction.RenderInstruction = renderInstruction;
List<IdentifiableObject> items = new List<IdentifiableObject>() { session.GetObject(tcmUri) };
List<PublicationTarget> targets = new List<PublicationTarget>() { engine.PublishingContext.PublicationTarget };
PublishEngine.Publish(items, publishInstruction, targets, priority);
session.Dispose();
}
// called with
PublishTransaction currentTransaction = TemplateUtils.GetPublishTransaction(engine);
TemplateUtils.Publish(engine, itemUri, currentTransaction.Creator, currentTransaction.Priority);
Your code seems to have the three things I "normally" forget:
the class is public
it extends TcmExtension
it has a TcmExtension attribute
If you've registered the class correctly in the configuration file, it should just be a matter of restarting the relevant module(s). In this case I'd expect those to be the Publisher and TcmServiceHost services.
After restarting those modules and triggering a publish action, you should see an event being logged (in the Windows event viewer) that your extension is being loaded.
If that even shows, it means your assembly is being loaded into the relevant Tridion process and the class is being recognized and instantiated.
If at this stage your handler doesn't fire you may have to consider listening to a different event. Whenever I want to interact with the publishing, I end up listening for the SaveEventArgs of a PublishTransaction, instead of the PublishOrUnPublishEventArgs on the Page.

Resources