繁体   English   中英

使用Unity依赖注入和Xamarin.Forms的依赖链

[英]Chain of dependencies using Unity Dependency Injection and Xamarin.Forms

我是依赖注入的新手,并且正在使用Xamarin.Forms,Prism和Unity开发应用程序。 据我所知,使用DI时,您想向类提供/注入服务,这样他们就不必获取它们。 导致类不了解服务实现。

这意味着使用构造函数注入而不是使用容器来解析服务。 也可以在这里看到http://structuremap.github.io/quickstart

我的设置:

[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
{ }

现在,如果我尝试解决IFoo,将引发异常: System.MissingMethodException: Default constructor not found for type Foo此处发生了什么?

我也尝试过向Foo添加一个空的构造函数,但这导致Bar为null并迫使我从IUnityContainer解析它。

据我所知,Xamarin表单依赖项服务(看起来好像您正在使用)大致不提供构造函数注入。 因此,如果要进行基于构造函数的注入,则需要使用其他容器服务。

如果要使用内置的Forms服务,则对代码的以下更改应该起作用。

[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
{ }

然后设置对象:

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

否则,您可能需要研究另一个DI框架。

感谢@snowCrabs,我了解到Xamarin.Forms不利于依赖注入。 因此,我决定创建一个基类,以通过反射来解决依赖项。

使用Xamarin DepedencyService的主要动机是因为我喜欢您可以使用[assembly: Xamarin.Forms.Dependency(typeof(Foo))]来注册您的类的方式。 这意味着在我的App项目中,我不需要进行任何注册。 我所要做的只是添加对我的库项目的引用,并且DependencyService会为我注册它,使我可以立即解析该接口以供使用。

编码:

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 !
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM