Способ наполнить коллекцию Unity - PullRequest
14 голосов
/ 10 июня 2011

У меня есть два примера классов

class ClassToResolve
{
    private List<CollectionItem> _coll;

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

class CollectionItem
{
    //...
}

и мне нужно разрешить ClassToResolve

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

            );

Теперь я решаю это таким образом

var classToResolve = new ClassToResolve(
            new List<CollectionItem>()
                {
                    unity.Resolve<CollectionItem>(),
                    unity.Resolve<CollectionItem>(),
                    unity.Resolve<CollectionItem>()
                }
            );

Есть ли способ разрешить ClassToResolve с Unity, используя динамическую регистрацию?

Ответы [ 4 ]

45 голосов
/ 11 июня 2011

Unity поймет, что зависимости T[] (массив) - это список вещей (но не IEnumerable<T> и не List<T>).Когда вы изменяете конструктор ClassToResolve на CollectionItem[] вместо List<CollectionItem>, вы можете настроить CollectionItem типы следующим образом:

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

Хитрость в том, чтобы назвать все регистрации,Регистрация по умолчанию (без имени) никогда не будет частью зависимости последовательности в Unity.

Теперь вы можете разрешить ClassToResolve без необходимости его регистрации:

container.Resolve<ClassToResolve>();

Если вы предпочитаете вводList<CollectionItem> Вы можете добавить следующую регистрацию:

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

А для IEnumerable<CollectionItem> вы можете добавить следующую строку:

container
  .RegisterType<IEnumerable<CollectionItem>, CollectionItem[]>();
0 голосов
/ 28 декабря 2015

@ Steven ответ совершенно правильный, я просто хочу предложить другой способ решения проблемы.

Ради лучшего и более чистого кода, оно того стоитопределить интерфейс для всех элементов коллекции.

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.

Теперь регистрационный код для контейнера Unity будет намного проще:

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

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

и код разрешения такой же:

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

Я надеюсь, что Microsoft добавит поддержку IEnumerable<> в следующую версию Unity, чтобы нам не нужно было регистрировать IEnumerable<IMyClass>.

0 голосов
/ 11 июня 2011

Используйте это

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 голосов
/ 11 июня 2011

Вы должны зарегистрировать свой класс в единстве

container.RegisterType()

Лучше использовать интерфейс

...