我正在查看一些试图学习MEF的代码:我理解如何导入示例服务但是ifound看起来像是在构造函数中导入一个集合。
IObservableCollection在哪里实例化并填充?导入自定义类时,它很容易遵循,但在导入集合时,从哪个项目填充?
private readonly IObservableCollection<NetworkServiceType> _observableNetworkServiceTypes;
[ImportingConstructor]
public MyConstructor (IObservableCollection<NetworkServiceType>
observableNetworkServiceTypes)
{
_observableNetworkServiceTypes = observableNetworkServiceTypes;
}
答案 0 :(得分:1)
我看到问题已被编辑,但希望这个答案仍有帮助。
我相信你理解的问题的第一部分。 IObservableCollection<NetowrkServiceType>
应该由实例化这个类的人实例化;这意味着他们也有责任准备传递给构造函数。 DI和其他可能/可能涉及的事情可以帮助解决这个问题,但在这种情况下,DI负责所有。
您了解类的实例化和传入方式,但集合中的项目,实例化的位置。嗯,这可能会有所不同,但由于这是一个集合,集合中应该已经有一系列项目。然而;因为这也是参考,这些项目可能会改变其他地方;这意味着它们可能在实例化之后填充或者谁知道......甚至可能在列表的枚举期间。 不安全地假设他们已经实例化来编写安全代码,但是它也是合理的,假设它应该是;换句话说,您需要考虑是否要使用传入的引用或在构造函数中复制它,以便您拥有自己的集合引用。
希望在编辑之前帮助解决原始问题;我看到你仍然代表下面的评论。我猜想IEnumerableCollection<NetworkServiceType>
确实有IEnumerable<T>
以及其他IEnumerableCollection<T>
的基础,但IEnumerableCollection
是一个独特的界面(不是我所知道的.NET)所以我可以&# 39;肯定地说。 (并且只是为了这样说;制作一个名为Enumerable
的类型是多余的,因为一个集合应该已经是可枚举的...)无论如何,回到这一点。你最初说,&#34;当导入IEnumerable时,我找不到项目的填充位置。&#34;我希望分享这一点,希望它有所帮助......当某些内容被引用或引用为IEnumerable
,IEnumerable<T>
或yield
时,它更像是你&#39;重新引用一个函数或委托,当被调用时返回一个值。该功能或方法有一个占位符,当它被同一个呼叫者再次呼叫时,它可以从它停止的地方接收;基本上允许您在迭代中调用时从同一函数返回多个项目。一种方法是使用Enumerable
关键字,您将在示例中看到。返回值可以是已引用的对象,也可以是在调用时实例化的对象。 Enumerable
还有更多内容,但现在让我们离开它。
这意味着当您引用foreach (var item in items)
类型时,您从枚举中预期的项目可能存在,也可能不存在。您总是只是引用一种获取项目的方法(以便更容易理解)。我在这里使用术语查询,虽然它在使用Linq和SQL时更相关,但想法是相同的。我们可以引用一个查询,在我们调用它之前永远不会得到任何项目。
考虑这个小应用程序,例如希望有助于说明上面的所有jibber jabber。这是一个可以复制和粘贴的小型控制台应用程序。在第10行(yield return Activator.CreateInstance<T>();
)上放置一个断点,在第18行放置一个断点(foreach
。请注意,在我们执行18之前,我们已达到第10行的断点,即使我们已经在线上引用了项目9.事实上,如果我们从未在此应用程序中使用Activator.CreateInstance<T>();
(或以任何方式迭代项目),那么我们将永远不会实例化新对象(意味着Enumerable
永远不会被调用。 )直到我们迭代项目(我称之为查询)我们才真正获得新对象。
注意:这并不是说这是你在问题中实例化的内容,因为我认为它不是。我只是简单说明.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
}
类型。
{{1}}
答案 1 :(得分:0)
我通过搜索
解决了这个问题[Export(typeof(IObservableCollection<NetworkServiceType>))]