C# 在构造函数中导入IEnumerable
我正在浏览一些代码,试图学习MEF:我理解如何导入示例服务,但我发现一些东西看起来像是在构造函数中导入集合 IObservableCollection在哪里实例化和填充?导入自定义类时很容易理解,但导入集合时,项从何处填充C# 在构造函数中导入IEnumerable,c#,.net,mef,C#,.net,Mef,我正在浏览一些代码,试图学习MEF:我理解如何导入示例服务,但我发现一些东西看起来像是在构造函数中导入集合 IObservableCollection在哪里实例化和填充?导入自定义类时很容易理解,但导入集合时,项从何处填充 private readonly IObservableCollection<NetworkServiceType> _observableNetworkServiceTypes; [ImportingConstructor] public MyConstruc
private readonly IObservableCollection<NetworkServiceType> _observableNetworkServiceTypes;
[ImportingConstructor]
public MyConstructor (IObservableCollection<NetworkServiceType>
observableNetworkServiceTypes)
{
_observableNetworkServiceTypes = observableNetworkServiceTypes;
}
private readonly IObservableCollection\u observeenetworkservicetypes;
[导入构造函数]
公共MyConstructor(IObservableCollection
ObservableNet(工作服务类型)
{
_ObservableNet工作服务类型=ObservableNet工作服务类型;
}
我通过搜索
[Export(typeof(IObservableCollection<NetworkServiceType>))]
[导出(typeof(IObservableCollection))]
我看到问题已被编辑,但希望这个答案仍然有用
问题的第一部分我相信你能理解。IObservableCollection
应由实例化该类的人实例化;也就是说,他们还负责将这些信息传递给构造函数。DI和其他可以/可能参与帮助解决此问题的事情,但在这种情况下,DI仍需负责
您了解类是如何实例化和传入的,但不了解集合中的项,它们在哪里实例化。这可能会有所不同,但因为这是一个集合,所以集合中应该已经有一个项目数组。然而;由于这也是通过参考,这些项目可能会在其他地方发生变化;这意味着它们可能会在实例化后填充,或者谁知道呢。。。甚至在列表枚举期间。假设它们已经被实例化以编写安全代码是不安全的,但是假设它们应该被实例化也是合乎逻辑的;换句话说,你需要考虑如果你想在你的构造函数中使用传入的引用或者复制它,这样你就有了自己对集合的引用。
并希望在编辑之前对原始问题有所帮助;我看到你在下面的评论中仍然代表着这一点。我想,IEnumerableCollection
确实有一个IEnumerable
的基础以及其他基础,但是IEnumerableCollection
是一个独特的接口(不是我所知道的.NET),所以我不能肯定。(为了说明这一点,创建名为IEnumerableCollection
的类型是多余的,因为集合应该已经可以枚举了……)总之,回到正题。您最初会说,“当导入IEnumerable时,我找不到填充项的来源。”我想与大家分享这一点,希望它能有所帮助。。。当某个对象被称为或引用为Enumerable
、IEnumerable
或IEnumerable
时,它更像是引用一个函数或委托,调用时返回一个值。该函数或方法有一个占位符,当同一个调用者再次调用它时,它可以选择它停止的地方;基本上允许您在迭代中调用时从同一个函数返回多个项。一种方法是使用yield
关键字,您将在示例中看到。返回值可以是已引用的对象,也可以是在调用时实例化的对象。还有更多的可枚举的,但现在我们就到此为止
这意味着,当您引用一个可枚举的
类型时,您期望从枚举中得到的项目可能存在,也可能不存在。您总是简单地引用一个方法来获取项(以便更容易理解)。我在这里使用术语查询,虽然它在使用Linq和SQL时更为相关,但其思想是相同的。我们可以有一个对查询的引用,在调用它之前永远不会得到任何项
以这个小应用程序为例,希望它能帮助说明上面所有的jibber jabber。这是一个小的控制台应用程序,你可以复制和粘贴。在第10行(foreach(items中的var item)
)上放置一个断点,在第18行(yield return Activator.CreateInstance();
)上放置一个断点。请注意,即使第9行已经有了对items的引用,我们还是先到达了第10行断点。事实上,如果我们从未使用foreach
(或者以任何方式迭代项)在这个应用程序中,我们将永远不会实例化新对象(意思是Activator.CreateInstance();
永远不会被调用)。直到我们迭代项(我称之为查询项),我们才真正得到新对象。
注意:这并不是说问题中的实例化就是这样做的,因为我假设不是这样。我只是说明.NET是如何查看可枚举
类型的
using System;
using System.Collections.Generic;
namespace Question_Answer_Console_App
{
class Program
{
static void Main(string[] args)
{
// A reference to IEnumerable<T>
// Behaves much like a function when used in a loop.
var items = GetItems<object>();
// For each works on IEnumerable types and internally calls the GetEnumerator() method.
// GetEnumerator() returns IEnumerator<T> which has 1 property and 2 methods :: Current, MoveNext(), and Reset()
// It basically calls GetEnumerator() and then MoveNext() and Current to give us the results
foreach (var item in items)
Console.WriteLine(item);
//Here's an example of the loop above written manually just to help you visualize it.
var enumerator = items.GetEnumerator();
while (enumerator.MoveNext())
Console.WriteLine(enumerator.Current);
//Finally; we can't write syntax but here's a method (seen below) that's much like the foreach syntax.
ForEach(items, item => Console.WriteLine(item));
Console.Read();
}
static void ForEach<T>(IEnumerable<T> items, Action<T> action)
{
IEnumerator<T> enumerator = items.GetEnumerator();
iterateItems();
void iterateItems()
{
// Notice that it's not actually until we get HERE calling MoveNext() that the yield return Activator.CreateInstance<T>() is actually called in our application.
// And even now we don't have a reference to it ourselves; it's just placed into the Current property of the IEnumerator<T> type.
var hasAnotherItem = enumerator.MoveNext();
if (hasAnotherItem)
{
// HERE is where we finally gain our own reference to the instantiated object for this example.
T currentItem = enumerator.Current;
action.Invoke(currentItem);
iterateItems();
}
}
}
static IEnumerable<T> GetItems<T>()
{
yield return Activator.CreateInstance<T>();
}
}
// Outputs:
// System.Object
// System.Object
// System.Object
}
使用系统;
使用System.Collections.Generic;
命名空间问题\答案\控制台\应用程序
{
班级计划
{
静态void Main(字符串[]参数)
{
//对IEnumerable的引用
//在循环中使用时,其行为非常类似于函数。
var items=GetItems();
//For each处理IEnumerable类型并在内部调用GetEnumerator()方法。
//GetEnumerator()返回IEnumerator,它有1个属性和2个方法::Current、MoveNext()和Reset()
//它基本上调用GetEnumerator(),然后调用MoveNext()和Current来给出结果
foreach(项目中的var项目)
控制台写入线(项目);
//下面是上面手动编写的循环示例,目的是帮助您将其可视化。
var枚举器=items.GetEnumerator();
while(枚举数.MoveNext())
Console.WriteLine(枚举器.Current);
//最后,我们不能编写语法,但这里有一个方法(如下所示)非常类似于foreach语法。
ForEach(items,item=>Console.WriteLine(item));
Console.Read();
}
静态空位ForEach(IEnumer