0

I'm new to Dependency Injection, and I'm developing an App using Xamarin.Forms, Prism and Unity. So as far as I know, when using DI you want to supply/inject services to classes so they don't have to get them. Resulting in classes that have no knowledge of service implementations.

That means using Constructor Injection instead of using the Container to resolve the services. Also seen here http://structuremap.github.io/quickstart.

My setup:

[assembly: Xamarin.Forms.Dependency(typeof(Foo))]
public class Foo : IFoo
{
    public IBar Bar { get; private set; }

    public Foo(IBar bar)
    {
        Bar = bar;
    }
}

[assembly: Xamarin.Forms.Dependency(typeof(Bar))]    
public class Bar : IBar
{ }

Now if I would try to resolve IFoo an exception is thrown: System.MissingMethodException: Default constructor not found for type Foo What is going on here?

I have also tried adding an empty constructor to Foo, but this results in Bar being null and forces me to resolve it from the IUnityContainer.

7
  • 1
    Your last remark is very confusing - if container.Resolve<IBar>() works than unity should be able to construct Bar just fine... Commented Aug 15, 2017 at 16:24
  • Simple answer - don't use Unity for new development because it is a dead project and you are very unlikely to get any support for it. Use one of the ~35 other .NET DI containers that are being actively maintained instead. Commented Aug 15, 2017 at 20:55
  • The problem appears to be your registration ignoring all the words you used it looks like you are using the Forms built in dependency service. Try registering the Bar as a Bar and not as a Foo.... also we can argue till the cows come home about property VS constructor injection but you can achieve what you want both ways Commented Aug 15, 2017 at 21:38
  • @snowCrabs Sorry, that's a typo. Commented Aug 16, 2017 at 7:15
  • @AlexeiLevenkov Yes it's very confusing Commented Aug 16, 2017 at 7:16

2 Answers 2

1

Roughly put as far as I can tell the Xamarin forms dependency services(which it looks like you are using) doesn't provide constructor injection. So if you want to do constructor based injection you will need to use a different container service.

IF you want to use the built in Forms service the following changes to your code should work..

[assembly: Xamarin.Forms.Dependency(typeof(Foo))]
public class Foo : IFoo
{
public IBar Bar { get; set; }

 public Foo(IBar bar)
 {
    Bar = bar;
 }
}

[assembly: Xamarin.Forms.Dependency(typeof(Bar))]    
public class Bar : IBar
{ }

Then to get your object set:

  var myFoo =  Xamarin.Forms.Dependency.Get<IFoo>();
  myFoo.Bar = Xamarin.Forms.Dependency.Get<IBar>();

Otherwise you might want to look into another DI framework.

Sign up to request clarification or add additional context in comments.

1 Comment

You are correct :) it seems Xamarin does not facilitate Dependency Injection. I ended up solving it by using a base class, ill add the code as new answer.
0

Thanks to @snowCrabs, I learned that Xamarin.Forms does not facilitate Dependency Injection. So I decided to make a base class to enable the resolving of dependencies via reflection.

My main motivation for using the Xamarin DepedencyService is because I like the way you can use [assembly: Xamarin.Forms.Dependency(typeof(Foo))] to register your classes. Which means in my App project, I don't have to do any registering. All I have to do it add a reference to my library project and the DependencyService will register it for me, allowing me to immediately resolve the interface for usage.

The code:

public ServiceBase()
{
    IEnumerable<PropertyInfo> dependencyProperties;
    var dependencyAttribute = typeof(Microsoft.Practices.Unity.DependencyAttribute);

    // DependencyService.Get<> requires a type parameter so we have to call it by using reflection
    var dependencyServiceGet = typeof(DependencyService).GetRuntimeMethod("Get", new Type[] { typeof(DependencyFetchTarget) });

    // Get the properties from our derrived type (accessed by using "this")
    dependencyProperties = this.GetType().GetTypeInfo().DeclaredProperties;

    //Check if any properties have been tagged with the DependencyAttribute
    dependencyProperties = dependencyProperties.Where(x =>
    {
        return x.CustomAttributes.Any(y => y.AttributeType == dependencyAttribute);
    });

    foreach (var prop in dependencyProperties)
    {
        // Add the type parameter to the Get-method
        var resolve = dependencyServiceGet.MakeGenericMethod(prop.PropertyType);

        // Now resolve the property via reflection: DependencyService.Get<PropertyType>();
        var service = resolve.Invoke(null, new object[] { DependencyFetchTarget.GlobalInstance });

        if (service == null)
            throw new InvalidOperationException($"Herke.Forms.Core.ServiceBase: Dependency could not be resolved, did you forget to register?{Environment.NewLine}Type: {prop.PropertyType.FullName}{Environment.NewLine}Suggested code: \"[assembly: Dependency(typeof( >ImplementatingClass< ))]\"");

        // Fill property value
        prop.SetValue(this, service);
    }
}

[assembly: Xamarin.Forms.Dependency(typeof(Bar))]    
public class Bar : IBar
{ }

[assembly: Xamarin.Forms.Dependency(typeof(Foo))]
public class Foo : ServiceBase, IFoo
{
    [Microsoft.Practices.Unity.Dependency]
    public IBar Bar { get; set; }

    // Foo can use Bar now !
}

1 Comment

I know this is 3.5 years ago, a lifetime in the coding world, but today, this can be used in Xamarin for a more normal DI framework: learn.microsoft.com/en-us/dotnet/core/extensions/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.