在特定示例中注册简单类型

时间:2016-06-20 07:38:08

标签: dryioc

考虑以下

ClassA有一个构造函数,它接受MasterClassstring的实例,并公开名为Names string[]的属性。

ClassB有一个带IJuicePresserIEnumerable<string>的构造函数。

ClassC有一个带IEnumerable<string>的构造函数。

手动我会做这样的事情把它们绑在一起。

var masterClass = new MasterClass();
var juicePresser = JuicePresser.Create("default");
var classA = new ClassA(masterClass, "string");
var names = classA.Names;
var classB = new ClassB(juicePresser, names as IEnumerable<string>);
var classC = new ClassC(Array.Reverse(names));

如何设置DryIoc来为我处理这些注册/解决方案?

1 个答案:

答案 0 :(得分:3)

将所有这些运行时名称从构造函数移动到相应的方法可能更好。但这里是匹配的DryIoc设置原样:

Live on .NET Fiddle

using System;
using System.Collections.Generic;
using System.Linq;
using DryIoc;

public class Program
{
    public static void Main()
    {
        var c = new Container();

        c.Register<MasterClass>();

        c.Register<JuicePresser>(Made.Of(() => JuicePresser.Create("default")));

        // an example how to inject a primitive value: "string" in this case 
        c.Register<ClassA>(made: Parameters.Of.Type<string>(_ => "string"));

        // service key is optional, just to distinguish the list of strings for consumer.
        c.Register<string[]>(
            Made.Of(_ => ServiceInfo.Of<ClassA>(), factory => factory.Names),
            serviceKey: "names"); 

        // register reverse names using ReverseHelper method
        c.Register<string[]>(
            Made.Of(() => ReverseHelper(Arg.Of<string[]>("names"))),
            serviceKey: "reverse-names"); 

        // specify the names and required type (string[]) for injection
        c.Register<ClassB>(made: Parameters.Of.Type<IEnumerable<string>>(typeof(string[]), serviceKey: "names"));

        // specify reverse names for injection
        c.Register<ClassC>(made: Parameters.Of.Type<string[]>(serviceKey: "reverse-names"));

        var classB = c.Resolve<ClassB>();
        var classC = c.Resolve<ClassC>();


        Console.WriteLine(string.Join(" - ", classB.Names.ToArray()));
        // outputs: a - string - z

        Console.WriteLine(string.Join(" - ", classC.Names));
        // outputs: z - string - a
    }

    public static T[] ReverseHelper<T>(T[] target) {
        Array.Reverse(target);
        return target;
    }

    public class MasterClass {}

    public class JuicePresser 
    {
        public readonly string Name;

        private JuicePresser(string name) { Name = name; }

        public static JuicePresser Create(string name) 
        {
            return new JuicePresser(name);
        }
    }

    public class ClassA 
    {
        public readonly string[] Names;

        public ClassA(MasterClass master, string name) {
            Names = new[] { "a", name, "z" }; // for example
        }
    }

    public class ClassB 
    {
        public readonly JuicePresser Presser;   
        public readonly IEnumerable<string> Names;

        public ClassB(JuicePresser presser, IEnumerable<string> names) {
            Presser = presser;
            Names = names;
        }
    }

    public class ClassC
    {

        public readonly string[] Names;

        public ClassC(string[] names) {
            Names = names;
        }
    }
}

更新

用以下内容解释部分:

c.Register<string[]>(
    Made.Of(_ => ServiceInfo.Of<ClassA>(), factory => factory.Names),
    serviceKey: "names"); 

DryIoc不仅支持使用构造函数来创建服务,还支持静态和实例方法(工厂方法),属性和字段。这是wiki topic

在上面的示例中,我们使用Names对象的ClassA属性作为工厂方法来注册服务类型&#34; string []&#34;使用服务密钥&#34;名称&#34;。

让我们详细了解一下:

// Registering service of ClassA. It means that it can be resolved / injected directly,
// or/and we can use it as a factory for resolving further services
c.Register<ClassA>(made: Parameters.Of.Type<string>(_ => "string"));

// Registering service of type "string[]"
c.Register<string[]>(
    // Made.Of enables specifying factory method to use for "string[]" resolution, instead default constructor selection rules.
    Made.Of(
        // 1) Specifying what factory object should be used,
        // Here we say to use ClassA service registered in container 
        requestNotUsedHere => ServiceInfo.Of<ClassA>(), 

        // 2) Specify that Names property of resolved ClassA object
        // should be used for "string[]" resolution
        classA => classA.Names),

    // As the "string[]" is not very distinctive (unique) service type 
    // (you might register other "string[]" with different meaning), 
    // we identify the names with "names" service key. So when injected or
    // resolved, you need to specify the service key in addition to type.
    serviceKey: "names");

如果您想注册静态工厂方法,属性,字段,那么您不需要指定request => ServiceInfo.Of<TFactory>()部分。 BTW,request参数可用于工厂的条件选择。

相关问题