Call WebView page method from referenced WinRT Component with AllowForWeb class - webview

I have a XAML page with WebView inside (for example MainPage.xaml). Also I have WinRT Component with class marked with [AllowForWeb] attribute. This component is referenced from project where MainPage.xaml located and in code-behind AddWebAllowedObject method is used. And I can't reference main project back because of circular dependency.
How to call MainPage.xaml.cs methods from component class? Very usual situation. Is there are some standard way to do it?
For example. I have a method inside RT component that could be called from JavaScript
public void ShowMessage(string message)
{
// I want to call here function from MainPage.xaml.cs
}

How to call MainPage.xaml.cs methods from component class? Very usual situation. Is there are some standard way to do it?
Yes, you can pass the method from MainPage.xaml.cs to Windows Runtime Component through delegate(Currently it's very limited to use delegate in Runtime Component using C#, see this case, so I use C++ as demo).
For Runtime Component Class MyClass.h:
public delegate Platform::String^ MyFunc(int a, int b);
public ref class MyClass sealed
{
public:
MyClass();
static Platform::String^ MyMethod(MyFunc^ func)
{
Platform::String^ abc=func(4, 5);
return abc;
}
};
And you can use the delegate in code behind like below:
using MyComponentCpp;
private void myBtn_Click(object sender, RoutedEventArgs e)
{
String abc=MyClass.MyMethod(MyMethod);
myTb.Text = abc;
}
private String MyMethod(int a, int b)
{
return (a.ToString() + b.ToString());//replace this line with your own logic.
}
And here is the complete Demo: TestProject.

Thankfully to #Elvis Xia who has gived me idea, I has found a solution how to do it without C++.
I have create a third project as Class Library. It doesn't has restrictions to use Action. This library I have referenced from main project and from WinRT component. Code of class inside library:
public class BridgeClass
{
public static event Action<string> MessageReceived;
public static void Broadcast(string message)
{
if (MessageReceived != null) MessageReceived(message);
}
}
Code inside main project with webview is:
// place somewhere
BridgeClass.MessageReceived += ShowMessage;
// ....... and add a method
void ShowMessage(string msg)
{
}
And now i can call this code from WinRT component:
public void ShowMessage(string message)
{
BridgeClass.Broadcast("lalala");
}

Related

Xamarin Android specific Ioc in MvvmCross constructor issue

tldr: Is there any way I can choose which constructor to use when I register a type?
I have followed the instructions to create a platform specific inversion of control as outlined in Inversion of control.
In your core project, you can declare an interface and you can use
that interface in your classes there ...
In each UI project, you can then declare the platform-specific
implementation ...
You can then register these implementations in each of the
platform-specific Setup files - e.g. you could override
MvxSetup.InitializeFirstChance
So in my core project I have defined the following interface
public interface IJob
{
void AddAction(Action action);
}
In my Android project I have implemented the interface as follows
public class CustomJob: Job, IJob
{
private Action _action;
public CustomJob(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
public CustomJob() : base(new Params
(Jobs.Priority.MID
).RequireNetwork().Persist())
{
//_action = action;
}
public override void OnAdded()
{
}
protected override void OnCancel(int p0, Throwable p1)
{
}
public override void OnRun()
{
_action.Invoke();
}
protected override RetryConstraint ShouldReRunOnThrowable(Throwable p0, int p1, int p2)
{
return RetryConstraint.Cancel;
}
public void AddAction(Action action)
{
_action = action;
}
}
And I overrode the implementation of InitializeFirstChance in Setup.cs
protected override void InitializeFirstChance()
{
Mvx.IoCProvider.RegisterType<IJob, CustomJob>();
base.InitializeFirstChance();
}
However, I get the following stacktrace at runtime
{MvvmCross.Exceptions.MvxIoCResolveException: Failed to resolve
parameter for parameter javaReference of type IntPtr when creating
CustomJob. You may pass it as an argument at
MvvmCross.IoC.MvxIoCContainer.GetIoCParameterValues (System.Type type,
System.Reflection.ConstructorInfo firstConstructor,
System.Collections.Generic.IDictionary2[TKey,TValue] arguments)
[0x0005a] in
C:\projects\mvvmcross\MvvmCross\IoC\MvxIoCContainer.cs:648 at
MvvmCross.IoC.MvxIoCContainer.IoCConstruct (System.Type type,
System.Collections.Generic.IDictionary2[TKey,TValue] arguments)
[0x00031] in
C:\projects\mvvmcross\MvvmCross\IoC\MvxIoCContainer.cs:413
Is there any way I can choose which constructor to use when I register a type? Thank you.
AFAIK you can't choose which constructor the Mvx's IoC engine will choose.
So one way is to make another class that implements your IJob that has a reference to Job internally and in the implementation of the class you pass the action to the Job implementation.
public class JobHandler : IJob
{
private Job _customJob;
public JobHandler()
{
this._customJob = new CustomJob();
}
public void AddAction(Action action)
{
this._customJob.AddAction(action);
}
}
If you want you can do an IJobHandler that inherits IJob so that you can use that interface for the JobHandler implementations and the IJob for you actual Job
Another way is to add stub parameters to the parameterless constructor so that it takes more parameters than the other and gets elected by the IoC engine (I'm not entirely sure that it would work, but I think so). But it is a bit messy.
Another way is you to tell the IoC engine how you want to construct your IJob:
Mvx.IoCProvider.RegisterType<IJob>(() => new CustomJob());
HIH

How to inject a list with different implementations of the same interface in a nested module scenario via Guice?

There is an interface DCE, which is implemented by a class DCEImpl which has a dependency, say, string S, which it gets via its constructor.
The universe of S is limited, say S can only take values {'A','B','C'}.
There is an already existing Guice module that accepts the value of S in its constructor, and then binds the interface DCE to the correctly initialized version of DCEImpl.
public class DCEModule extends AbstractModule {
private final String s;
public DCEModule(String s){
this.s = s;
}
protected void configure() {
bind(DCE.class).toInstance(new DCEImpl(s));
}
}
Now I have a class C which needs a List<DCE> with all the 3 implementations (actually a lot more than 3, using 3 for example purpose).
I want to inject this list via Guice in C. To do that, I created a new module DCEPModule, which will provide a List<DCE> in this way:
#Provides
List<DCE> getDCE() {
for(String s: S){
Module m = new DCEModule(s);
install(m);
Injector injector = Guice.createInjector(m);
listDomains.add(injector.getInstance(DCE.class));
}
}
My problem is that I don't want to call a new injector in this module, because DCEPModule will be installed by a different module.
public class NewModule extends AbstractModule {
protected void configure() {
install(DCEPModule);
}
}
I want a way to get the List<DCE> without explicitly creating a new injector in DCEPModule.
You can achieve this by using a Multibinder (javadoc, wiki).
Here’s an example:
public class SnacksModule extends AbstractModule {
protected void configure(){
Multibinder<Snack> multibinder = Multibinder.newSetBinder(binder(), Snack.class);
multibinder.addBinding().toInstance(new Twix());
  multibinder.addBinding().toProvider(SnickersProvider.class);
  multibinder.addBinding().to(Skittles.class);
}
}
Now, the multibinder will provide a Set<Snack>. If you absolutely need a List instead of a Set, then you can add a method to your module like this:
#Provides
public List<Snack> getSnackList(Set<Snack> snackSet) {
return new ArrayList(snackSet);
}
You can add implementations to the same Multibinding in more than one module. When you call Multibinder.newSetBinder(binder, type) it doesn’t necessarily create a new Multibinding. If a Multibinding already exists for for that type, then you will get the existing Multibinding.

Dart: how to reference methods of classes

While writing library documentation I need to be able to reference (i.e. link to) methods from other classes (in the same library) but with the same method name (i.e. reference the delegating method from the docs of the one that is doing the work).
I have tried ClassName.method (does not work) and directly using the method (references the same class method).
Any ideas?
Thanks.
/// [B.someMethod] ..
/// [someMethod] ..
class A {
void someMethod() {
}
}
/// [A.someMethod]
/// [someMethod]
class B {
void someMethod() {
}
}
/// [A.someMethod]
void main() {
new A().someMethod();
}
All references in the doc comments work for me in this example, but sometimes DartEditor shows them only as links after a delay or after some other edits.
Its a docgen issue/bug - can be monitored here: https://code.google.com/p/dart/issues/detail?id=22144

ExecutionEngineException: Attempting to JIT compile method

public class StaticDataContainer<T> where T : IStaticData {
protected static Dictionary<int, T> data;
public static void init(string jsonString){
//It work fine in Unity,But in Xcode iOS,it will show an error below:
//ExecutionEngineException: Attempting to JIT compile method
//'System.Collections.Generic.Dictionary`2<int, AD>:.ctor ()'
//while running with --aot-only.
data = new Dictionary<int, T> ();
I refer to:http://answers.unity3d.com/questions/250803/executionengineexception-attempting-to-jit-compile.html
Your application makes use of some generic type that was missed during AOT compile.
And solution is:The problem can usually be fixed by including a "dummy" class that references the missing types.
But I dont' know what dummy class is.
How can I solve it?
Here's how I do it. I create a file with name AOTDummy.cs in a project with following structure (adapted for your problem):
public static class AOTDummy
{
public static void Dummy()
{
System.Collections.Generic.Dictionary<int, AD> dummy01;
}
}

Why does my Ninject DI application fail with an ActivationException?

I'm new to IoC/DI frameworks. The first one I am trying is the Ninject framework. It seems straightforward, but I can't get my console application to run. I keep getting an ActivationException stating:
"Error activating MainWindow: the StandardProvider returned an instance of type FutureRealisticDateManager, which is not compatible with the requested service.
Using default binding from MainWindow to FutureRealisticDateManager (via StandardProvider)
declared by DateBindingModule.Load()
Activation path:
1) active request for MainWindow
from Program.Main()
using default binding from MainWindow to FutureRealisticDateManager (via StandardProvider)
declared by DateBindingModule.Load()"
My code is very simple. Here is my Program file...
class Program
{
static void Main(string[] args)
{
IKernel k = new StandardKernel(new DateBindingModule());
MainWindow mw = k.Get<MainWindow>();
mw.Show();
Console.ReadLine();
}
}
Here is my ninject binding module...
public class DateBindingModule : StandardModule
{
public override void Load()
{
Bind<MainWindow>().To<FutureRealisticDateManager>();
}
}
Here is the class that receives the injected class...
class MainWindow
{
private IRealisticDateManager _d;
[Inject]
public MainWindow(IRealisticDateManager dateManager)
{
_d = dateManager;
}
public void Show()
{
Console.WriteLine("*** MainWindow [" + _d.GetRealisticDate().ToString() + "] ");
}
}
And here is the actual class being injected...
public class FutureRealisticDateManager : TestNinject.IRealisticDateManager
{
public DateTime GetRealisticDate()
{
return DateTime.Now.AddDays(15);
}
}
And finally the simple interface that the injected class should implement...
public interface IRealisticDateManager
{
DateTime GetRealisticDate();
}
Can anybody see what I am doing wrong?
It fails because your binding is not right:
Bind<MainWindow>().To<FutureRealisticDateManager>();
FutureRealisticDataManager does not inherit from MainWindow.
Instead you should write:
Bind<IRealisticDateManager>().To<FutureRealisticDateManager>();
This tells Ninject to return FutureRealisicDateManager whenever IRealisicDateManager is requested.
This way when you call k.Get<MainWindow>() kernel will inject FutureRealisticDateManager to the constructor.

Resources