【问题标题】:Way to fill collection with Unity使用 Unity 填充集合的方法
【发布时间】:2011-06-10 09:19:26
【问题描述】:

我有两个示例类

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>()
                }
            );

有没有办法通过 Unity 使用动态注册来解决 ClassToResolve?

【问题讨论】:

  • 你的例子没有多大意义。为什么要向ClassToResolve 注入多个相同的实例?
  • 它们不相同。仅在示例中它们是相同的。我简化了这个例子。事实上,这个从一个基类/接口继承/实现的对象列表,或者不同配置对象的列表。这与模式设计“Director”非常相似,其中 ClassToResolve = Director 和 CollectionItem=Strategy(如 IRunnable)
  • 都是同一个接口还是不同接口?你实际上想要发生什么?
  • 这是一个非常常见的用例。一个对象使用其他对象的列表。但是问题已经解决了。

标签: c# .net dependency-injection inversion-of-control unity-container


【解决方案1】:

Unity 将理解T[](数组)依赖项是事物的列表(但不是IEnumerable&lt;T&gt;,也不是List&lt;T&gt;)。当您将ClassToResolve 的构造函数更改为采用CollectionItem[] 而不是List&lt;CollectionItem&gt; 时,您可以按如下方式配置您的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&lt;CollectionItem&gt;,您可以添加以下注册:

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

对于IEnumerable&lt;CollectionItem&gt;,您可以添加以下行:

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

【讨论】:

  • -1 你错了 Unity 不理解 IEnumerable 除非你明确注册它。
  • @Hasan:你是对的。我太快了。 Unity 默认理解 T[],而不是 IEnumerable&lt;T&gt;。我修好了。
  • 太好了,这正是我需要的!将是正确的 container.RegisterType, CollectionItem[]>();
  • name参数是关键!
【解决方案2】:

@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>();

我希望微软在下一版本的 Unity 中添加IEnumerable&lt;&gt; 支持,这样我们就不需要注册IEnumerable&lt;IMyClass&gt;

【讨论】:

  • 对于代码示例,您能否将“var”替换为具体的数据类型?我非常感谢这个答案,但是代码示例中的“var”……并不能帮助读者恕我直言。谢谢。我猜它是 IEnumerable,但很高兴看到你有什么。
【解决方案3】:

你应该统一注册你的班级

container.RegisterType()

最好使用界面

【讨论】:

  • 示例中没有注册详细信息。因为,这是个问题——如何注册这个集合以便用 Unity 自动解析它?
【解决方案4】:

使用这个

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

【讨论】:

  • 谢谢。但我更喜欢不要使用 Unity 作为服务定位器。
猜你喜欢
  • 2014-01-11
  • 2020-01-22
  • 2021-07-28
  • 1970-01-01
  • 2014-10-31
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 2022-01-15
相关资源
最近更新 更多