Way to fill collection with Unity

依然范特西╮ 提交于 2019-11-28 07:37:41

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[]>();
Tohid

@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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!