.NET Core scripting backend namespace issues for Serialization, Reflection and more

Hi,

I’m writing here since the documentation on: https://docs.unity3d.com/Manual/windowsstore-missingtypes.html is very limited.
I have to compile to UWP with .NET Core scripting backend. It works using IL2CPP, but that’s not an option (.NET Core scripting backend is required).

I’m getting alot of reference rewriter errors, so I guess I have to write compiler directives, but I’m not sure which namespaces to use due to the limited documentation.
Example of error:

“Reference rewriter: Error: type System.Runtime.Serialization.SerializationInfo doesn’t exist in target framework…”

All our custom exceptions yields an error of that kind.

Other namespace ref errors include:

  • System.AppDomain

  • System.Reflection.MethodInfo System.Delegate::get_Method()

  • System.Boolean System.Type::get_IsAbstract()

  • System.Reflection.Assembly System.Reflection.Assembly::GetCallingAssembly()

Am I missing some documentation and if so can someone point me in that direction?

I’m using 2017.1.1f1

Thanks!

It’s a difference between .NETCore and regular .NET. In case of reflection you need to use TypeInfo instead of Type, MethodInfo instead of Method etc. Microsofts documentation usually provides info on which types/methods are available and which not.
Since you get reference rewriter errors, it means that you either selected to compile your scripts using different profile in player settings or you have dlls in your project. In case of first it’s best to select .NET Core in player settings, so you get compiler errors. For later you need compatible dlls (the ones compiled for UWP).

While this is off-topic, do you mind going into details of why that is the case? We’re planning to deprecate .NET scripting backend in the future, so knowing what problems people are having with IL2CPP will help us make that transition easier for everybody.

@Aurimas-Cernius : Thanks for the answer. Yes, we use our own dlls, and it’s those that I have to make compatible. We build Unitypackages with native dll’s in separate projects and import them into a test UWP project.

@Tautvydas-Zilys : We have a large project coming out and we have to release on the Windows Platform (and many other). I don’t know much about the exact issue, because another team was working on that part, but apparently there’s a WiFi communication issue in the current version of Unity if IL2CPP is used. We’ve already been in contact with you guys about it, and it’s going to be fixed in a future release. So hopefully it works when you deprecate .NET scripting backend. :wink:

*“test UWP project” is meant for testing the native stuff. Later on they are imported into the real projects.

I did some more digging.
For some reason Exceptions are not serializable in Core (normally the Exception class implements the ISerializable interface and has a constructor that takes the SerializationInfo and StreamingContext parameters).
So I tried just excluding the entire constructor that uses that base constructor and those parameters with NETFX_CORE. For some reason, I still get the error when I’m trying to compile to UWP with the .NET Core scripting backend.
Will the compiler preprocessor not survive the compilation to dlls? If not, I probably have to make a dll for each scripting backend to get it to work?

No. Preprocessor directives in your project include or exclude code at the time you compile the DLL. Once it’s compiled, it’s compiled. You will have to have a separate DLL for .NET Core.

Your DLL needs to be built specifically for .NET Core if you’re going to use the .NET backend. You can use a .NET assembly if you’re using IL2CPP, but not for the .NET backend. Make a new VS project and choose Windows Universal → Class Library. Include UnityEngine.dll and WinRTLegacy.dll from the Unity folder. You will be able to easily see which classes/members are not supported in .NET Core because VS will throw compiler errors until you make your code conform to the .NET Core API. Your best bet is to write static helper functions which include preprocessor if’s for .NET and .NET Core versions, then change all your code to reference those helper functions instead of calling things like System.Type.GetFields directly.

Here are a few to get you started. Add a NETCORE compilation symbol to your .NET Core project.

public static class ReflectionTools {

    public static bool IsValueType(Type type) {
#if !NETCORE
        return type.IsValueType;
#else
        return type.GetTypeInfo().IsValueType;
#endif
    }

    public static bool DoesTypeImplement(Type type, Type baseOrInterfaceType) {
#if !NETCORE
        return baseOrInterfaceType.IsAssignableFrom(type);
#else
        return baseOrInterfaceType.GetTypeInfo().IsAssignableFrom(type.GetTypeInfo());
#endif
    }

    public static bool IsGenericType(Type type) {
        if(type == null) return false;
#if !NETCORE
        return type.IsGenericType;
#else
        return type.GetTypeInfo().IsGenericType;
#endif
    }

    public static Type[] GetGenericArguments(Type type) {
        if(type == null) return null;
#if !NETCORE
        return type.GetGenericArguments();
#else
        return type.GetTypeInfo().GenericTypeArguments;
#endif
    }
 
    public static IEnumerable<FieldInfo> GetFields(Type type) {
        if(type == null) return null;
#if !NETCORE
        return type.GetFields();
#else
        return type.GetTypeInfo().DeclaredFields;
#endif
    }

    public static IEnumerable<FieldInfo> GetFields(Type type, BindingFlags bindingFlags) {
        if(type == null) return null;
#if !NETCORE
        return type.GetFields((System.Reflection.BindingFlags)bindingFlags);
#else
        return type.GetTypeInfo().DeclaredFields;
#endif
    }
 
    public static IEnumerable<PropertyInfo> GetProperties(Type type) {
        if(type == null) return null;
#if !NETCORE
        return type.GetProperties();
#else
        return type.GetTypeInfo().DeclaredProperties;
#endif
    }

    public static IEnumerable<PropertyInfo> GetProperties(Type type, BindingFlags bindingFlags) {
        if(type == null) return null;
#if !NETCORE
        return type.GetProperties((System.Reflection.BindingFlags)bindingFlags);
#else
        return type.GetTypeInfo().DeclaredProperties;
#endif
    }
}

Thanks for the reply @guavaman it really led me in the right direction! :slight_smile: