Подтвердить что ты не робот

Способ заполнения коллекции Unity

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

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, используя динамическую регистрацию?

4b9b3361

Ответ 1

Unity поймет, что зависимости T[] (array) - это список вещей (но не 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[]>();

Ответ 2

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

container.RegisterType()

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

Ответ 3

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

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

Ответ 4

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