none
ReflectionOnlyAssemblyResolve can not load assembly using IValueConverter RRS feed

  • Question

  • I am using:

           AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve +=
                    OnAssemblyResolve;
    
           Assembly inputAssembly = Assembly.ReflectionOnlyLoadFrom(this.inputFileName);
           Type[] inputAssemblyTypes = inputAssembly.GetTypes();
    
           private Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
            {
                try
                {
                    Assembly assembly = Assembly.ReflectionOnlyLoad(args.Name);
    

    To load an assembly for 'ReflectionOnlyLoad' but if the assembly contains classes implementing IValueConverter it fails to load - I get several errors for dependent assemblies like:

    Cannot resolve dependency to assembly 'blah blah' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event

    ... but I am using the ReflectionOnlyAssemblyResolve event.

    If I pre-load the dependent assemblies I get somewhat more informative error messages like:

    Cannot resolve dependency to Windows Runtime type 'Windows.UI.Xaml.Data.IValueConverter'. When using the ReflectionOnly APIs, dependent Windows Runtime assemblies must be resolved on demand through the ReflectionOnlyNamespaceResolve event.

    ... but I am using the ReflectionOnlyAssemblyResolve event.

    If I remove usage of IValueConverter the assembly loads...

    What is happening? Is there a way to fix this?


    Friday, April 20, 2018 11:41 PM

Answers

  • @ellipsisware,

    I don't find why it is necessary for you to reflect the IValueConverter here. If your desktop app is the service part and your UWP app is the UI part. Why not directly use Desktopbridge technology like this sample mentioned:https://github.com/Microsoft/DesktopBridgeToUWP-Samples/tree/master/Samples/AppServiceBridgeSample

    For reflection specific part, I don't have the experience on this kind of issue. But it seems some already successfully doing this, like here. But it's only getting types. What I always heard is that we need to modify the manifest to add platform target support and the specific API need to have DualApiPartitionAttribute. And IValueConverter actually do not have this attribute. 

    Best regards,

    Barry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by ellipsisware Friday, April 27, 2018 8:48 PM
    Thursday, April 26, 2018 7:13 AM
  • Thank you Barry.

    I did not explain myself well in explaining why I was reflecting on IValueConverter. my main application does not need to know about IValueConverter usage. IvalueConverter was used to replace TypeConverterAttribute which is not available in the UWP.

    I uses reflection in the desktop environment for various purposes, in this case I wrote a separate program to assist me in attributing my code to use the DataContract attributes because serialization using the Serializable attribute does not working in the UWP, the code for the dll that I was examining used IValueConverter and loading the assembly failed - I wanted to know why and although you stated that "I don't have the experience on this kind of issue" the link that you provided 'here' gave the solution.

    What was needed was support for the ReflectionOnlyNamespaceResolve event in addition to the ReflectionOnlyAssemblyResolve event.

    Here is the working code for the console application.

    using System;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.InteropServices.WindowsRuntime;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += 
                    OnReflectionOnlyAssemblyResolve;
    
                WindowsRuntimeMetadata.ReflectionOnlyNamespaceResolve += 
                    OnReflectionOnlyNamespaceResolve;
    
                try
                {
                    Assembly inputAssembly = 
                        Assembly.ReflectionOnlyLoadFrom(_inputFilename);
                    Type[] inputAssemblyTypes = inputAssembly.GetTypes();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
    
                Console.ReadLine();
            }
    
            private static string _inputFilename = 
                @"..\..\..\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
    
            private static System.Reflection.Assembly 
                OnReflectionOnlyAssemblyResolve(object sender, 
                ResolveEventArgs args)
            {
                try
                {
                    Assembly assembly = 
                        Assembly.ReflectionOnlyLoad(args.Name);
    
                    return assembly;
                }
                catch(Exception e)
                {
                    Console.WriteLine(
                        $"OnReflectionOnlyAssemblyResolve failed {e.Message}");
                }
                return null;
            }
    
            private static void OnReflectionOnlyNamespaceResolve(
                object sender, NamespaceResolveEventArgs e)
            {
                string path =
                    WindowsRuntimeMetadata.ResolveNamespace(e.NamespaceName, 
                    Enumerable.Empty<string>()).FirstOrDefault();
                if (path == null)
                {
                    Console.WriteLine($"OnReflectionOnlyNamespaceResolve failed" +
                        "to find namespace {e.NamespaceName}");
                    return;
                }
    
                e.ResolvedAssemblies.Add(Assembly.ReflectionOnlyLoadFrom(path));
            }
        }
    }
    

    One can see that 

    OnReflectionOnlyNamespaceResolve

    is called once to resolve "Windows.UI.Xaml.Data"

    • Marked as answer by ellipsisware Friday, April 27, 2018 8:49 PM
    Friday, April 27, 2018 8:48 PM

All replies

  • I am using:

    Microsoft Visual Studio Community 2017
    Version 15.6.4
    VisualStudio.15.Release/15.6.4+27428.2015
    Microsoft .NET Framework
    Version 4.7.02556
    Installed Version: Community
    Visual C++ 2017   00369-60000-00001-AA929
    Microsoft Visual C++ 2017
    Visual F# Tools 10.1 for F# 4.1   00369-60000-00001-AA929
    Microsoft Visual F# Tools 10.1 for F# 4.1
    Application Insights Tools for Visual Studio Package   8.11.10212.1
    Application Insights Tools for Visual Studio
    ASP.NET and Web Tools 2017   15.0.40314.0
    ASP.NET and Web Tools 2017
    Azure App Service Tools v3.0.0   15.0.40215.0
    Azure App Service Tools v3.0.0
    C# Tools   2.7.0-beta3-62715-05. Commit Hash: db02128e6e3c4bdfc93e6ec425ac9162b4d4fe80
    C# components used in the IDE. Depending on your project type and settings, a different version of the compiler may be used.
    Common Azure Tools   1.10
    Provides common services for use by Azure Mobile Services and Microsoft Azure Tools.
    Cookiecutter   15.6.18072.2
    Provides tools for finding, instantiating and customizing templates in cookiecutter format.
    JavaScript Language Service   2.0
    JavaScript Language Service
    JavaScript Project System   2.0
    JavaScript Project System
    JavaScript UWP Project System   2.0
    JavaScript UWP Project System
    Microsoft Azure Tools   2.9
    Microsoft Azure Tools for Microsoft Visual Studio 2017 - v2.9.51212.2
    Microsoft JVM Debugger   1.0
    Provides support for connecting the Visual Studio debugger to JDWP compatible Java Virtual Machines
    Microsoft MI-Based Debugger   1.0
    Provides support for connecting Visual Studio to MI compatible debuggers
    Microsoft Visual C++ Wizards   1.0
    Microsoft Visual C++ Wizards
    Microsoft Visual Studio VC Package   1.0
    Microsoft Visual Studio VC Package
    NuGet Package Manager   4.6.0
    NuGet Package Manager in Visual Studio. For more information about NuGet, visit http://docs.nuget.org/.
    ProjectServicesPackage Extension   1.0
    ProjectServicesPackage Visual Studio Extension Detailed Info
    Python   15.6.18072.2
    Provides IntelliSense, projects, templates, debugging, interactive windows, and other support for Python developers.
    Python - Django support   15.6.18072.2
    Provides templates and integration for the Django web framework.
    Python - IronPython support   15.6.18072.2
    Provides templates and integration for IronPython-based projects.
    Python - Profiling support   15.6.18072.2
    Profiling support for Python projects.
    R Tools for Visual Studio   1.3.40104.1351
    Provides project system, R Interactive window, plotting, and more for the R programming language.
    Test Adapter for Boost.Test   1.0
    Enables Visual Studio's testing tools with unit tests written for Boost.Test.  The use terms and Third Party Notices are available in the extension installation directory.
    Test Adapter for Google Test   1.0
    Enables Visual Studio's testing tools with unit tests written for Google Test.  The use terms and Third Party Notices are available in the extension installation directory.
    TypeScript Tools   15.6.20202.3
    TypeScript Tools for Microsoft Visual Studio
    Visual Basic Tools   2.7.0-beta3-62715-05. Commit Hash: db02128e6e3c4bdfc93e6ec425ac9162b4d4fe80
    Visual Basic components used in the IDE. Depending on your project type and settings, a different version of the compiler may be used.
    Visual Studio Code Debug Adapter Host Package   1.0
    Interop layer for hosting Visual Studio Code debug adapters in Visual Studio
    Visual Studio Tools for CMake   1.0
    Visual Studio Tools for CMake
    Visual Studio Tools for Universal Windows Apps   15.0.27428.01
    The Visual Studio Tools for Universal Windows apps allow you to build a single universal app experience that can reach every device running Windows 10: phone, tablet, PC, and more. It includes the Microsoft Windows 10 Software Development Kit.

    WiX Toolset Visual Studio Extension   0.9.21.62588
    WiX Toolset Visual Studio Extension version 0.9.21.62588
    Copyright (c) .NET Foundation and contributors. All rights reserved.

    Targeting .Net 4.6.2

    Friday, April 20, 2018 11:44 PM
  • Hello,

    Can you create a MVCE for us? The IValueConverter has two kinds, 1 and 2. One belongs to system namespace and 2 belongs to UWP UI type. Normally in UWP platform we will avoid reflection usage so I'm curios about details about your project. 

    Best regards,

    Barry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, April 23, 2018 9:18 AM
  • Hello Barry.

    Yes - I noted that there are two kinds of IValueConverter - not exactly ideal - I am using the UWP version, this is because my project is a desktop application that communicates with similar code in the UWP - the UWP code does not use reflection, that is a service provided by the desktop version.

    Originally my code used the TypeConverterAttribute but this is not available in the UWP so I decided to use the IValueConverer interface instead.

    Here is the example requested.

    Create a solution with two projects: ClassLibrary1 is a class library - it references Windows.Foundation.UniversalApiContract to get the second kind of IValueInterface

    using System;
    
    namespace ClassLibrary1
    {
        public class Class1 : IValueConverter
        {
            public object Convert(object value, Type targetType, 
                object parameter, string language)
            {
                throw new NotImplementedException();
            }
    
            public object ConvertBack(object value, Type targetType, 
                object parameter, string language)
            {
                throw new NotImplementedException();
            }
        }
    }

    The second project is the startup project - a console application:

    using System;
    using System.Reflection;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += 
                    OnReflectionOnlyAssemblyResolve;
                try
                {
                    Assembly inputAssembly = 
                        Assembly.ReflectionOnlyLoadFrom(_inputFilename);
                    Type[] inputAssemblyTypes = inputAssembly.GetTypes();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
    
                Console.ReadLine();
            }
    
            private static string _inputFilename = 
                @"..\..\..\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
    
            private static System.Reflection.Assembly 
                OnReflectionOnlyAssemblyResolve(object sender, 
                ResolveEventArgs args)
            {
                try
                {
                    Assembly assembly = 
                        Assembly.ReflectionOnlyLoad(args.Name);
    
                    return assembly;
                }
                catch(Exception e)
                {
                    Console.WriteLine(e.Message);
                }
                return null;
            }
        }
    }

    When using IValueConverter exceptions are thrown, comment it out and they are not.

    Thank you.


    • Edited by ellipsisware Monday, April 23, 2018 6:54 PM removed unused code
    Monday, April 23, 2018 6:46 PM
  • @ellipsisware,

    I don't find why it is necessary for you to reflect the IValueConverter here. If your desktop app is the service part and your UWP app is the UI part. Why not directly use Desktopbridge technology like this sample mentioned:https://github.com/Microsoft/DesktopBridgeToUWP-Samples/tree/master/Samples/AppServiceBridgeSample

    For reflection specific part, I don't have the experience on this kind of issue. But it seems some already successfully doing this, like here. But it's only getting types. What I always heard is that we need to modify the manifest to add platform target support and the specific API need to have DualApiPartitionAttribute. And IValueConverter actually do not have this attribute. 

    Best regards,

    Barry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by ellipsisware Friday, April 27, 2018 8:48 PM
    Thursday, April 26, 2018 7:13 AM
  • Thank you Barry.

    I did not explain myself well in explaining why I was reflecting on IValueConverter. my main application does not need to know about IValueConverter usage. IvalueConverter was used to replace TypeConverterAttribute which is not available in the UWP.

    I uses reflection in the desktop environment for various purposes, in this case I wrote a separate program to assist me in attributing my code to use the DataContract attributes because serialization using the Serializable attribute does not working in the UWP, the code for the dll that I was examining used IValueConverter and loading the assembly failed - I wanted to know why and although you stated that "I don't have the experience on this kind of issue" the link that you provided 'here' gave the solution.

    What was needed was support for the ReflectionOnlyNamespaceResolve event in addition to the ReflectionOnlyAssemblyResolve event.

    Here is the working code for the console application.

    using System;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.InteropServices.WindowsRuntime;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += 
                    OnReflectionOnlyAssemblyResolve;
    
                WindowsRuntimeMetadata.ReflectionOnlyNamespaceResolve += 
                    OnReflectionOnlyNamespaceResolve;
    
                try
                {
                    Assembly inputAssembly = 
                        Assembly.ReflectionOnlyLoadFrom(_inputFilename);
                    Type[] inputAssemblyTypes = inputAssembly.GetTypes();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
    
                Console.ReadLine();
            }
    
            private static string _inputFilename = 
                @"..\..\..\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
    
            private static System.Reflection.Assembly 
                OnReflectionOnlyAssemblyResolve(object sender, 
                ResolveEventArgs args)
            {
                try
                {
                    Assembly assembly = 
                        Assembly.ReflectionOnlyLoad(args.Name);
    
                    return assembly;
                }
                catch(Exception e)
                {
                    Console.WriteLine(
                        $"OnReflectionOnlyAssemblyResolve failed {e.Message}");
                }
                return null;
            }
    
            private static void OnReflectionOnlyNamespaceResolve(
                object sender, NamespaceResolveEventArgs e)
            {
                string path =
                    WindowsRuntimeMetadata.ResolveNamespace(e.NamespaceName, 
                    Enumerable.Empty<string>()).FirstOrDefault();
                if (path == null)
                {
                    Console.WriteLine($"OnReflectionOnlyNamespaceResolve failed" +
                        "to find namespace {e.NamespaceName}");
                    return;
                }
    
                e.ResolvedAssemblies.Add(Assembly.ReflectionOnlyLoadFrom(path));
            }
        }
    }
    

    One can see that 

    OnReflectionOnlyNamespaceResolve

    is called once to resolve "Windows.UI.Xaml.Data"

    • Marked as answer by ellipsisware Friday, April 27, 2018 8:49 PM
    Friday, April 27, 2018 8:48 PM