Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues with Xamarin.iOS #34

Closed
Dids opened this issue Aug 15, 2017 · 11 comments
Closed

Issues with Xamarin.iOS #34

Dids opened this issue Aug 15, 2017 · 11 comments

Comments

@Dids
Copy link

Dids commented Aug 15, 2017

I've been working on a .NET Standard 2.0 library for a while now, an using Scrutor with FromApplicationDependencies() has been working fine in my unit tests.

However, when Scrutor is used in Xamarin.iOS both FromApplicationDependencies() and FromDependencyContext(DependencyContext.Load(Assembly.GetEntryAssembly())) throw an exception:

The type initializer for 'Microsoft.Extensions.DependencyModel.DependencyContextLoader' threw an exception.

...

System.NotImplementedException: The method or operation is not implemented.

...

  at System.AppContext.GetData (System.String name) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.12.0.18/src/mono/mcs/class/referencesource/mscorlib/system/AppContext/AppContext.cs:46 
  at Microsoft.Extensions.DependencyModel.DependencyContextPaths.GetCurrent () [0x00000] in <8241b70107294c1cb31f55eb9c49a4a8>:0 
  at Microsoft.Extensions.DependencyModel.DependencyContextPaths..cctor () [0x0000a] in <8241b70107294c1cb31f55eb9c49a4a8>:0 

I tried getting around this by doing the following:

var entryAssembly = Assembly.GetEntryAssembly();
var entryDependencyAssemblies = entryAssembly.GetReferencedAssemblies();
List<Assembly> scanAssemblies = new List<Assembly> { entryAssembly };
foreach (var assemblyName in entryDependencyAssemblies)
{
    var assembly = Assembly.Load(assemblyName);
    scanAssemblies.Add(assembly);
}

...

.FromAssemblies(scanAssemblies)

Unfortunately Scrutor is not finding any classes when I do this. Not sure if it matters, but I specify an array of base types that I scan for, like this:

.AddClasses(classes => classes.Where(c => scanTypes.Contains(c.BaseType)))

Note that the debugger is showing that scanAssemblies does contain the correct assemblies, and I can see the types I want under DefinedTypes.

Even a hacky workaround would be very much appreciated at this point!

@khellang
Copy link
Owner

khellang commented Aug 23, 2017

Hi! Sorry it took some time to answer. I've been on vacation for a couple of weeks 😄

I'm not sure what to do about the unimplemented System.AppContext.GetData method. I guess the DependencyContext stuff isn't really meant to be used on Xamarin products (yet?). Are you using the latest version of Xamarin.iOS/Mono? @akoeplinger, is this something you (or someone else on the Mono team) are aware about? Any tips?

Unfortunately Scrutor is not finding any classes when I do this.

All assembly selection overloads goes through the FromAssemblies method, so I'm pretty confident that it works. If you're saying that all the correct assemblies are present in the scanAssemblies collection, I'm guessing this has something to do with filtering.

What happens if you remove the Where clause? Try setting a breakpoint inside and see if it gets called at all.

@akoeplinger
Copy link

Hey! Yep, the System.AppContext.GetData() API was implemented in Mono 5.4, though that branch didn't make it in time for the upcoming Xamarin.iOS 10.14 (at least currently), so it'll be in whatever the release after that is called :)

A workaround is to use AppDomain.CurrentDomain.GetData() (which is how AppContext.GetData() is implemented today).

@khellang
Copy link
Owner

Thanks for the information! I guess there's nothing more to do than work around it for now and update when the next release is out 😄

A workaround is to use AppDomain.CurrentDomain.GetData() (which is how AppContext.GetData() is implemented today).

Yeah, the problem is that this is futher down the stack. This is actually called by a Microsoft library ( Microsoft.Extensions.DependencyModel) 😢

@akoeplinger
Copy link

akoeplinger commented Aug 23, 2017

@khellang yeah, just had a look and they're using AppContext.GetData() in NS1.6+ and AppDomain.CurrentDomain.GetData() on NET46.

What are you using Microsoft.Extensions.DependencyModel for? From the description on NuGet it's Abstractions for reading .deps files. which shouldn't apply to Mono/Xamarin?

@khellang
Copy link
Owner

What are you using Microsoft.Extensions.DependencyModel for? From the description on NuGet it's Abstractions for reading .deps files. which shouldn't apply to Mono/Xamarin?

Yeah, this API (or even library) wasn't really made with Xamarin in mind. I've only tested it on .NET and .NET Core. The API is basically for when you want to scan for types in your (typically web) application's dependencies. AFAIK, this requires the compilation to actually embed a .deps file in the assembly, which probably doesn't happen on Mono/Xamarin anyway.

@Dids
Copy link
Author

Dids commented Aug 23, 2017

In my case, I'm actually using this in a custom MVVM framework, as it helps with automatically finding views/view models (which I bind together automatically), finding services and working hand in hand with IOC/DI.

At any rate, would you mind keeping this issue open until it's fixed in Mono? Just figured others running into the same issue could just check here, and see that it's still "open", even though it's not an issue in Scrutor. :)

@khellang
Copy link
Owner

At any rate, would you mind keeping this issue open until it's fixed in Mono?

Nope, not at all 😄 There's probably something we can do for Xamarin as well. We can probably cross-compile (will NuGet use the Xamarin-specific assembly instead of netstandard?) and have a different way of getting the referenced assemblies through reflection, similar to what you've already done.

@khellang
Copy link
Owner

@Dids Pushed a new version, 2.1.0 to NuGet with a new method, FromAssemblyDependencies, that does more or less what your code above does. FromApplicationDependencies will now also fall back to this method, using the entry assembly when the DependencyContext fails to load, i.e. on Xamarin/Mono.

@Dids
Copy link
Author

Dids commented Aug 23, 2017

That's amazing, thank you!

@khellang
Copy link
Owner

I'd still like to get to the bottom of why you're not getting any classes registered though. Have you tried AssignableToAny(scanTypes)?

@khellang
Copy link
Owner

I'm closing this due to lack of activity. I'm assuming everything sorted itself out with the new methods 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants