Way to fill collection with Unity

后端 未结 4 502
粉色の甜心
粉色の甜心 2020-12-09 05:06

I have two example classes

class ClassToResolve
{
    private List _coll;

    public ClassToResolve(List coll)
          


        
相关标签:
4条回答
  • 2020-12-09 05:27

    @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>.

    0 讨论(0)
  • 2020-12-09 05:27

    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 讨论(0)
  • 2020-12-09 05:36

    You should register you class in unity

    container.RegisterType()
    

    It's better to use interface

    0 讨论(0)
  • 2020-12-09 05:46

    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[]>();
    
    0 讨论(0)
提交回复
热议问题