parse-community / Parse-SDK-dotNET

Parse SDK for .NET, Xamarin, Unity.
http://parseplatform.org
Apache License 2.0
323 stars 260 forks source link

Use of GetEntryAssembly within Parse SDK and a configurable replacement solution [Discussion] #321

Closed TobiasPott closed 4 years ago

TobiasPott commented 5 years ago

In several other issues this has come up and caused some problems when using the Parse SDK in projects targeting native platforms (e.g. Xamarin iOS/Android or Unity iOS/Android).

From my point of view GetEntryAssembly is used for a good reason and provides an expected behaviour as it ensures that version information used by the SDK for cache files and storage locations is based on the actual application and not the Parse.dll assembly.

I'm mostly using Parse within Unity3D applications which does not provide a reference to the entry assembly and requires a workaround to encapsulate the required information in a separate type (or change behaviour using compiler directives).

After thinking about this situation for a while and facing it over and over again I believe it would be possible to add an additional configuration to the SDK which is used to retrieve the required information (version numbers, product name, company name, etc.). This can be done in a similar fashion the platform plugins in 1.7 worked using an interface and a default implementation which targets .NET Standard behaviour and features.

If anyone would require a custom solution for a specific platform (e.g. iOS via Unity or Xamarin) It should be an easy way to create a custom implementation of the interface providing all required information (or overriding those not available compared to the default one).

I'm not sure if everything would work out like I imagine it at the moment but I'll give it a try in my forked repository and implement the described solution. My goal would be as little adjustments to the master branch as possible but the possibility to add custom implementations with very little work and without the need to dive into and recompile the ParseSDK source code.

I'm open for suggestions and considerations I might have missed yet or which problems might occur. Please don't hesitate to comment on this issue.

TobiasPott commented 5 years ago

Brief update on this from my side! I've looked over my Unity support code yesterday and stripped it from clutter and assembled everything into a shared interface definition and default implementation.

It can be found in the https://github.com/TobiasPott/Parse-SDK-dotNET/tree/feature/implement-target-platform-configurations feature branch. As for now the repository itself only contains a default implementation for .NET Standard which uses the same method calls as the Parse SDK did before (only implemented as an IParseTargetPlatform derived class to allow replacement).

I've also added a Platforms.md file which describes the structure behind my idea and gives an example implementation to use with Unity3D (which I've tested with the Parse-based application at work).

I'm not yet capable of providing an example for Xamarin but I'll have it on my list as the current approach nearly eliminates the hustle I have with adopting changes to the master branch and use them within Unity.

I'm now eager to get feedback on this one as I believe it is a valid way to reintroduce support for other platforms like Unity3D or Xamarin without having compiler flags or weird workarounds in the master branch. This said I would like to ask @TheFanatr @TomWFox and other contributors for their opinion.

Best regards

lunjio commented 4 years ago

Brief update on this from my side! I've looked over my Unity support code yesterday and stripped it from clutter and assembled everything into a shared interface definition and default implementation. It can be found in the https://github.com/TobiasPott/Parse-SDK-dotNET/tree/feature/implement-target-platform-configurations feature branch. As for now the repository itself only contains a default implementation for .NET Standard which uses the same method calls as the Parse SDK did before (only implemented as an IParseTargetPlatform derived class to allow replacement). I've also added a Platforms.md file which describes the structure behind my idea and gives an example implementation to use with Unity3D (which I've tested with the Parse-based application at work). I'm not yet capable of providing an example for Xamarin but I'll have it on my list as the current approach nearly eliminates the hustle I have with adopting changes to the master branch and use them within Unity. I'm now eager to get feedback on this one as I believe it is a valid way to reintroduce support for other platforms like Unity3D or Xamarin without having compiler flags or weird workarounds in the master branch. This said I would like to ask @TheFanatr @TomWFox and other contributors for their opinion. Best regards

What do you think if add public method: public static void PlatformInitialize() { EntryAssembly = Assembly.GetCallingAssembly(); } where EntryAssembly:

private static Assembly EntryAssembly
        {
            get
            {
            if(_entryAssembly == null && Assembly.GetEntryAssembly() == null)
                throw new ParseException(ParseException.ErrorCode.NotInitialized, "You must call PlatformInitialize() method in platform specific project.");
                return _entryAssembly = _entryAssembly ?? Assembly.GetEntryAssembly();
            }

            set
            {
                _entryAssembly = value;

            }
        }

also change calls to Assembly.GetEntryAssembly() to EntryAssembly. I cheked this on my Xamarin Forms project on Android, calling PlatformInitialize() in anroid project solves the problem, parse obtains information about correct Assembly, not about itself if we just call GetExecutingAssembly. I found a little bit complex you solution. I don't know how it works on Unity.

TobiasPott commented 4 years ago

@lunjio Thank you for your suggestion to solve the GetEntryAssembly problems encountered when using Xamarin. Unfortunately this would not cover the issue for Unity as far as I remember and some sort of configuration is required to cover all issues (different folder locations, assembly retrieval etc.). Your solution only covers the two cases (Xamarin.Android and by default .NET Standard).

But you gave me a quite useful hint that the assembly retrieval can be wrapped or simplified in my feature branch. I'll hope I can ponder about a way to make it a little bit more accessible and straight forward to use in the next days and push a new commit to the feature branch.