开发者

Way to fill collection with Unity

I have two example classes

class ClassToResolve
{
    private List<CollectionItem> _coll;

    public ClassToResolve(List<CollectionItem> coll)
    {
        _coll = coll;
    }
}

class CollectionItem
{
    //...
}

and I need to resolve ClassToResolve

var classToResolve = new ClassToResolve(
            new List<CollectionItem>()
                {
                    new CollectionItem(),
                    new CollectionItem(),
                    new CollectionItem()
                }

            );

Now I resolve it in a way

var classToResolve = new ClassToResolve(
            new List<CollectionItem>()
                {
                    unity.Resolve<CollectionItem>(),
             开发者_运维技巧       unity.Resolve<CollectionItem>(),
                    unity.Resolve<CollectionItem>()
                }
            );

Is there a way to resolve ClassToResolve with Unity using dynamic registration?


Unity will understand that T[] (array) dependencies are a list of things (but not IEnumerable<T>, nor List<T>). When you change the constructor of ClassToResolve to take an CollectionItem[] instead of a List<CollectionItem> you can configure your CollectionItem types as follows:

container.RegisterType<CollectionItem, CollectionItemA>("a");
container.RegisterType<CollectionItem, CollectionItemB>("b");
container.RegisterType<CollectionItem, CollectionItemC>("c");
container.RegisterType<CollectionItem, CollectionItemD>("d");

The trick here is to name all the registrations. A default (nameless) registration will never be part of a sequence dependency in Unity.

Now you can resolve ClassToResolve without the need to register it:

container.Resolve<ClassToResolve>();

If you rather inject List<CollectionItem> you can add the following registration:

container.RegisterType<IList<CollectionItem>, CollectionItem[]>();

And for IEnumerable<CollectionItem> you can add the following line:

container
  .RegisterType<IEnumerable<CollectionItem>, CollectionItem[]>();


@Steven's answer is perfectly correct, I just want to suggest another way to tackle the issue.

For the sake of a better and cleaner code, it is worth it to define an interface for all the collection items.

public interface IMyClass
{
    void DoSomething();
}

public abstract class MyClassBase : IMyClass
{
    abstract void DoSomething();
    // more code for the base class if you need it.
}

public class MyClassA : MyClassBase
{
    void virtual DoSomething()
    {
        // implementation here
    }
}

public class MyClassB : MyClassBase
{
    void virtual DoSomething()
    {
        // implementation here
    }
}

public class MyClassC : MyClassBase
{
    void virtual DoSomething()
    {
        // implementation here
    }
}

// etc.

Now the registration code for Unity container would be much more easier:

container.RegisterTypes(
    AllClasses.FromLoadedAssemblies().
        Where(type => typeof(IMyClass).IsAssignableFrom(type)),
    WithMappings.FromAllInterfaces,
    WithName.TypeName,
    WithLifetime.PerResolve);

container.RegisterType<IEnumerable<IMyClass>, IMyClass[]>();

and the resolve code is the same:

var allOfMyClasses = container.ResolveAll<IMyClass>();

I hope Microsoft add IEnumerable<> support to the next version of Unity so we won't need to register IEnumerable<IMyClass>.


You should register you class in unity

container.RegisterType()

It's better to use interface


Use this

class ClassToResolve:IEnumerable<CollectionItem>
{
    private List<CollectionItem> _coll;

    public ClassToResolve(IUnityContainer container)
    {
        _coll = container.ResolveAll<CollectionItem>();
    }

    public IEnumerator<CollectionItem> GetEnumerator()
    {
        return _coll.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public void Add(CollectionItem)
    {
        this._coll.Add(CollectionItem);
    }
}

now register you class
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜