Detect Universal App at Runtime in PCL

2019-08-31 22:05发布

问题:

Is there any way to detect that a main application is a Universal App (W10) from a Portable Class Library?

Thanks

回答1:

Out-of-the-box I do not think the functionality you are asking for is available in PCL, but here is a suggestion involving reflection that you might want to try.

It is adapted to the PCL Profile (328) you are using, involving .NET 4 and Silverlight 5. The GetPlatformName method needs to be somewhat adjusted if you want to for example switch to PCL profiles 111 and 259, since these profiles would have to rely on TypeInfo rather than Type.

Here is the proposed method and accompanying interface, which can be implemented in the Portable Class Library:

public static class RuntimeEnvironment
{
    public static string GetPlatformName()
    {
        var callingAssembly = (Assembly)typeof(Assembly).GetMethod("GetCallingAssembly").Invoke(null, new object[0]);
        var type = callingAssembly.GetTypes().Single(t => typeof(IPlatform).IsAssignableFrom(t));
        var instance = (IPlatform)Activator.CreateInstance(type);
        return instance.PlatformName;
    }
}

public interface IPlatform
{
    string PlatformName { get; }
}

Apart from the above code, you will also need to implement the IPlatform interface in each platform-specific application, for example like this:

public class UniversalPlatform : IPlatform
{
    public string PlatformName => "UWP";
}

In short, the GetPlatformName method instantiates the single class implementing the IPlatform interface in the calling (application) assembly, and returns the PlatformName property.

The Assembly.GetCallingAssembly method is not publicly exposed in any of the PCL profiles, but it is generally implemented and can therefore be accessed via reflection.

The GetPlatformName method is fully portable and can thus be consumed within the Portable Class Library itself, allowing you to make platform conditional decisions within the PCL code. The proposal does require minimal code efforts within each platform-specific application, since you do need to implement IPlatform, but maybe that is an acceptable price to pay?



回答2:

You have several ways: first:

  1. add PCL to main project (reference)
  2. create enum in PCL for determine type of OS (for ex. OperationSystemType)
  3. In main point (start) - for UWP it is App.cs pass right value to PCL

second (more flexible):

  1. Crete interface IApplicationProvider in any PCL
  2. Create implementation for each platform (in main project). You can add OSType property in interface (for ex.)
  3. Bind interface to implementation by IoC container in main project (App.cs)
  4. Get by IoC instance for interface and get right value


回答3:

One way to detect a platform from within a PCL is to try and load a type at runtime that is only available for that platform.

For example, for UWP, you could try to load type Windows.System.Profile.AnalyticsInfo, which is only available in a Windows 10 UWP application:

var win10Type = Type.GetType("Windows.System.Profile.AnalyticsInfo, Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime");

var isWin10UWP = win10Type != null;

It's not pretty, but it does work and the technique can be used to detect other platforms as well.