How to include another assembly in a Windows Phone 8 XAP - plugins

I would like to include another assembly in my XAP for Windows Phone without referencing it directly (like a plugin system) so I can load it at runtime and activate types from it but I can't find any kind of reference on this.
I mostly found out questions regarding how to load it once included but how to (correctly) include it, no.

You can add a compiled assembly (.dll file) to your WP8 project and set the file Build Action to 'Content'. Then you can try to load it as so :
var folder = await StorageFolder.GetFolderFromPathAsync(Path.Combine(Windows.ApplicationModel.Package.Current.InstalledLocation.Path, "Plugins", "Services"));
var files = await folder.GetFilesAsync();
var firstFile = files.FirstOrDefault();
var assy = Assembly.LoadFrom(firstFile.Path);
But Assembly.LoadFrom will fail since it's unsupported. You can still use this to load other binary content but not code.
All you can do is reference all 'plugins' or whatever assemblies you might need and not directly reference any type from these assemblies. By 'reference the assemblies' I mean right click on references (in the WP8 project) and "Add reference...".
You can then do this :
var assy = Assembly.Load("MyCompany.MyProject.WhateverAssembly");
var tp = typeof(IService);
var x = ass.GetTypes().Where(t => t.IsClass && tp.IsAssignableFrom(t)).SingleOrDefault();
Activator.CreateInstance(x);
Not very elegant but I could call it a workaround.

Related

How to dynamically load a JAR file with Vert.x JavaScript?

Using Vert.x JavaScript (3.8.4), I want to dynamically load a JAR file at runtime. This is necessary because that file might not exist when my Vert.x application gets started. Ideally, I would like to be able to use code like this:
// load custom JAR file
requireJar("path/to/dynamic.jar");
// use class from dynamically loaded package
var instance = new com.mydynamicpackage.MyCustomClass();
How can I achieve this?
You might find this answer to be helpful:
How to access external JAR files from JavaScript using Rhino and Eclipse?
Another approach that is valid would be to provide the jar with other means, i.e. not via a javascript implementation, to check afterwards, if it is available and then deal with the case if it is not.
java.lang.Class.forName( 'com.mydynamicpackage.MyCustomClass' )
This will throw an error, if MyCustomClass does not exist.
Loading jars at runtime might not be a good idea if you cannot determine they are loaded from a not trustworthy source. This is at least true for the java world.
Based on this answer, I have created the following JavaScript function for dynamically loading a class from a JAR file:
var requireJavaClass=(function(){
var method=java.net.URLClassLoader.class.getDeclaredMethod("addURL",java.net.URL.class);
method.setAccessible(true);
var cache={};
var ClassLoader=java.lang.ClassLoader;
var File=java.io.File;
return function(classname,jarpath){
var c=cache[classname];
if (c) return c;
if (jarpath) {
var cl=ClassLoader.getSystemClassLoader();
method.invoke(cl,new File(jarpath).toURI().toURL());
cl.loadClass(classname);
}
return cache[classname]=Java.type(classname);
}
})();
The equivalent to the snippet I posted in the my question would be:
var MyCustomClass=requireJavaClass("com.mydynamicpackage.MyCustomClass","path/to/dynamic.jar");
var instance = new MyCustomClass();
So far, I have only tested this with Vert.x 3.8.5 running in JRE8, i.e. I can't say if this also works in older Vert.x versions or with JRE9+.

Accessing Raw Gamer Profile Picture

I am using the new XBox Live API for C# (https://github.com/Microsoft/xbox-live-api-csharp) for official access through a UWP app.
I am able to authenticate fine and reference the XBox Live user in context.
SignInResult result = await user.SignInAsync();
XboxLiveUser user = new XboxLiveUser();
Success! However, I can't seem to find an appropriate API call to return XboxUserProfile or XboxSocialProfile. Both of these classes contain URLs to the player's raw gamer pics. After reviewing MSDN documentation and the GH library it isn't clear to me how this is achieved. Any help is greatly appreciated.
The below sample should work if you meet the following pre requisits:
Reference the Shared Project that contains the API from your project and don't reference the "Microsoft.Xbox.Services.UWP.CSharp" project
Copy all source code files from the "Microsoft.Xbox.Services.UWP.CSharp" project into your project
Include the Newtonsoft.Json NuGet package into your project
Steps 1 & 2 are important as this allows you to access the "internal" constructors which otherwise would be protected from you.
Code to retrieve the profile data:
XboxLiveUser user = new XboxLiveUser();
await user.SignInSilentlyAsync();
if (user.IsSignedIn)
{
XboxLiveContext context = new XboxLiveContext(user);
PeopleHubService peoplehub = new PeopleHubService(context.Settings, context.AppConfig);
XboxSocialUser socialuser = await peoplehub.GetProfileInfo(user, SocialManagerExtraDetailLevel.None);
// Do whatever you want to do with the data in socialuser
}
You may still run into an issue like I did. When building the project you may face the following error:
Error CS0103 The name 'UserPicker' does not exist in the current
context ...\System\UserImpl.cs 142 Active
If you get that error make sure you target Win 10.0 Build 14393.

TypeLite generate external modules?

I am trying to generate external modules rather than a type definition file. I believe I need to do the following:
Change the extension of the file to .ts instead of .d.ts.
Generate one file per module.
Add the key word "Export" in front of each interface and enum.
I was easily able to change the extension of the file by changing the "output extension" setting in the tt file.
I cannot figure out how to split the modules into separate files.
I cannot figure out how to add the Export key word to each interface.
TypeLITE doesn't support generating multiple files. This feature has been requested by several users, but I am not aware of a simple way to generate multiple files from the single tt file.
export keyword can't be added without changing source code of the library (TsGenerator.cs). This is very specific requirement, so I probably won't add it to the library.
TypeLite is a good project but lacking in Documentation and examples, it's open source so anyone can contribute and make it better.
As for creating a file per class i solved it using the code below.
private static void GenerateTypeScriptContracts(string assemblyFile, string outputPath)
{
// Clean TS Folder
System.IO.DirectoryInfo di = new DirectoryInfo(outputPath);
foreach (FileInfo file in di.GetFiles())
{
file.Delete();
}
// --
var assembly = Assembly.LoadFrom(assemblyFile);
// If you want a subset of classes from this assembly, filter them here
var models = assembly.GetTypes();
foreach (var model in models)
{
var generator = new TypeScriptFluent()
.WithConvertor<Guid>(c => "string")
.WithMemberFormatter((identifier) => Char.ToLower(identifier.Name[0]) + identifier.Name.Substring(1));
generator.ModelBuilder.Add(model);
// Generate TS interface definitions
var tsClassDefinitions = generator.Generate(TsGeneratorOutput.Properties | TsGeneratorOutput.Fields);
File.WriteAllText(Path.Combine(outputPath, "I" + model.FullName.Replace("ProjectName.DtoModels.", "") + ".ts"), tsClassDefinitions);
}
}

Can't save state in windows 8 [ Error The type or namespace name 'Common'

Can't save state in windows 8
{
Error The type or namespace name 'Common' ...does not exist in the namespace 'ProjectName' (are you missing an assembly reference?)
}
Everything below is the default code in my App.Xaml.cs file the only line I added was
ProjectNameSpace.Common.SuspensionManager.RegisterFrame(rootFrame, "appframe");
which is from the windows 8 tutorial here and I have followed part 1 before attempting this http://msdn.microsoft.com/en-us/library/windows/apps/hh986968.aspx. I have it working in another project that has the same references and using statements. There is only one namespace in the project and I even Rebuilt/Cleaned. Does anybody have any extra information?
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
ProjectNameSpace.Common.SuspensionManager.RegisterFrame(rootFrame, "appframe");
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
}
Window.Current.Content = rootFrame;
EDIT:
The problem was that I needed to add a basic page in my blank template. This auto generates some classes needed to do basic functionality. Below is a screenshot of the minimum items that the common folder needs to contain.
Do you have the Common folder present in your project? This folder is usually included in the Visual Studio 2012 App project templates (except the Blank App template) which contains a bunch of classes with boilerplate code for layout, styles and other functionality.
If you created your project with a Blank App template, you may not have this. To get it included, create a new Basic Page (Right-click on your Project > Add > New Item > (Visual C#)* > Basic Page), and Visual Studio will ask if you would like to create these files.
*I'm not sure what this is for VB .NET or WinJS, but I assume it would be the same structure.

RuntimeBinderException in the CSASPNETWebsite sample solution of Facebook C# SDK

I just started the CSASPNETWebsite website which is a sample example site uses the c# sdk and the dynamic keyword
The main page contain the following code:
var fb = new FacebookClient(this.CurrentSession.AccessToken);
dynamic myInfo = fb.Get("me");
lblName.Text = myInfo.name;
I got the following exception:
'Facebook.JsonObject' does not contain a definition for 'name'
from
myInfo.name;
(or myInfo.id or anything else that should be)
the type of myInfo at runtime is Facebook.JsonObject, is it should be anything else?
I have added references to Facebook.dll, Facebook.Web.dll and Facebook.Web.Mvc.dll
Thanks in advance,
Alon.
Find my mistake:
The references I add were for DLLs in the .net35 folder (which not contain all the dynamic keyword) instead of the SDK instead of the .net4 folder.
problem solved.