在构造函数中导入IEnumerable

时间:2018-06-18 15:36:49

标签: c# .net mef

我正在查看一些试图学习MEF的代码:我理解如何导入示例服务但是ifound看起来像是在构造函数中导入一个集合。

IObservableCollection在哪里实例化并填充?导入自定义类时,它很容易遵循,但在导入集合时,从哪个项目填充?

private readonly IObservableCollection<NetworkServiceType> _observableNetworkServiceTypes;

[ImportingConstructor]
public MyConstructor (IObservableCollection<NetworkServiceType> 
    observableNetworkServiceTypes)    
{
   _observableNetworkServiceTypes = observableNetworkServiceTypes;
}

2 个答案:

答案 0 :(得分:1)

我看到问题已被编辑,但希望这个答案仍有帮助。

我相信你理解的问题的第一部分。 IObservableCollection<NetowrkServiceType>应该由实例化这个类的人实例化;这意味着他们也有责任准备传递给构造函数。 DI和其他可能/可能涉及的事情可以帮助解决这个问题,但在这种情况下,DI负责所有。

您了解类的实例化和传入方式,但集合中的项目,实例化的位置。嗯,这可能会有所不同,但由于这是一个集合,集合中应该已经有一系列项目。然而;因为这也是参考,这些项目可能会改变其他地方;这意味着它们可能在实例化之后填充或者谁知道......甚至可能在列表的枚举期间。 不安全地假设他们已经实例化来编写安全代码,但是它也是合理的,假设它应该是;换句话说,您需要考虑是否要使用传入的引用或在构造函数中复制它,以便您拥有自己的集合引用。

希望在编辑之前帮助解决原始问题;我看到你仍然代表下面的评论。我猜想IEnumerableCollection<NetworkServiceType>确实有IEnumerable<T>以及其他IEnumerableCollection<T>的基础,但IEnumerableCollection是一个独特的界面(不是我所知道的.NET)所以我可以&# 39;肯定地说。 (并且只是为了这样说;制作一个名为Enumerable的类型是多余的,因为一个集合应该已经是可枚举的...)无论如何,回到这一点。你最初说,&#34;当导入IEnumerable时,我找不到项目的填充位置。&#34;我希望分享这一点,希望它有所帮助......当某些内容被引用或引用为IEnumerableIEnumerable<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>))]