【问题标题】:Using IEnumerable<> and creating a property with its type使用 IEnumerable<> 并使用其类型创建属性
【发布时间】:2013-02-05 21:10:47
【问题描述】:

我没有太多使用 Linq,也没有使用过 IEnumberable 类。以下是我遇到的问题的代码和解释。

public class EmailService : IEmailService
{
    #region Constructors

    #endregion

    #region Properties
    [ImportMany]
    public IEnumerable<IEmailAddressesProvider> AddressProviders { get; set; }

    #endregion

这些是我需要在 EmailService 类中使用的属性。这是电子邮件地址提供商的集合。

我需要使用其中存储的内容并将其连接到 ViewModel,就像我在这段代码的下一部分中处理这些其他属性一样。

IUserInteractionService uiService = AllianceApp.Container.GetExportedValue<IUserInteractionService>();
            IEmailSetupProvider provider = new EmailSetupProvider();
            EmailView ev = AllianceApp.Container.GetExportedValue<EmailView>();

            ev.ViewModel.ProviderName = AddressProviders;
            ev.ViewModel.Provider = provider;
            ev.ViewModel.Bcc = bccAddress;
            ev.ViewModel.Cc = ccAddress;
            ev.ViewModel.ToAddress = toAddress;
            ev.ViewModel.Body = body;
            ev.ViewModel.Subject = subject;
            ev.ViewModel.Attachments = attachments;

            return uiService.ShowDialog(ev, RegionNames.MainRegion);
        }

它说“地址提供者是我试图创建此属性的地方。

IEmailAddressesProvider 接口:

public interface IEmailAddressesProvider
{
    string ProviderName { get; }
    IEnumerable<EmailAddress> GetEmailUsers();
}

GetEmailUsers 方法(以防万一):

[Export(typeof(IEmailAddressesProvider))]
public class EmailAddressProvider : IEmailAddressesProvider
{
    #region Private Properties

    private static readonly IEncryptionService encryptionService = AllianceApp.Container.GetExportedValue<IEncryptionService>();

    #endregion

    public string ProviderName
    {
        get { return "Alliance Users"; }
    }

    public IEnumerable<EmailAddress> GetEmailUsers()
    {
        IUserRepository userRepo = AllianceApp.Container.GetExportedValue<IUserRepository>();
        IEnumerable<User> users = userRepo.GetAllUsers().Where(a => a.IsDeleted == false).OrderBy(a => a.UserID).AsEnumerable();

        List<EmailAddress> AddressList = new List<EmailAddress>();

        foreach (var user in users)
        {
            if (user.DisplayName != null && user.EmailAddress != null && user.DisplayName != string.Empty && user.EmailAddress != string.Empty)
                AddressList.Add(new EmailAddress() { DisplayName = encryptionService.DecryptString(user.DisplayName), Email = encryptionService.DecryptString(user.EmailAddress) });
        }

        AddressList.OrderBy(u => u.DisplayName);

        return AddressList;
    }
}

ProviderName 专用代码(在 EmailAddressesProvider.cs 中使用):

[Export(typeof(IEmailAddressesProvider))]
public class EmailAddressProvider : IEmailAddressesProvider
{
    #region Private Properties

    private static readonly IEncryptionService encryptionService = AllianceApp.Container.GetExportedValue<IEncryptionService>();

    #endregion

    public string ProviderName
    {
        get { return "Alliance Users"; }
    }
}

如果您需要查看我的代码,例如接口或视图模型,请告诉我。任何帮助将不胜感激!

【问题讨论】:

  • 但是有什么问题呢? ProviderName 似乎是单个提供者,因此是 IEmailAddressesProvider。那么,您想要所有可用的AddressProviders 中的一个名称吗?如果需要,是哪一个?
  • 我相信它只会显示其中一个,我认为哪一个将由一组不同的代码决定。我将发布我将使用的界面。
  • 已添加更多代码
  • @JLott - 即使有额外的代码,我仍然不知道问题是什么。您是否收到编译时错误?你不知道怎么做吗?

标签: c# linq interface viewmodel ienumerable


【解决方案1】:

就您的示例而言,您可以将IEnumerable&lt;T&gt; 视为List&lt;T&gt; 的同义词:它是对象的集合;可能只有一个,可能没有,可能是一百个。 IEnumerable 的作用远不止于此,但出于您的目的,这与您需要考虑的一样多。

在这段代码中:

[ImportMany]
public IEnumerable<IEmailAddressesProvider> AddressProviders { get; set; }

您要求 MEF 收集 IEmailAddressesProvider 的所有导出实现。你得到的是一个对象的集合:即使它只找到一个,你仍然得到一个只有一个元素的集合。在后面的行中:

ev.ViewModel.ProviderName = AddressProviders;

我猜左边是string,但右边是IEmailAddressesProvider 的集合。除了您可能实际上想要IEmailAddressesProviderProviderName 属性而不是整个对象这一事实之外,您还需要说明要使用集合中的哪个对象。有两种方法可以解决这个问题:

  1. 如果您知道IEmailAddressesProvider 的实现只有一种,那么将ImportMany 更改为Import 就像这样

    [Import]
    public IEmailAddressesProvider AddressProviders { get; set; }
    

    并将其他分配更改为ev.ViewModel.ProviderName = AddressProviders.ProviderName。请注意,一旦您导出 IEmailAddressesProvider 的第二个实现,这将中断,所以只有在您真的知道只能有一个时才这样做。

  2. 如果IEmailAddressesProvider 可能有多个实现,那么您需要找到您想要的具体实现。您可以使用 FirstOrDefault 之类的东西(正如其他答案所说)查询 AddressProviders 集合以找到正确的对象,然后使用该结果中的 ProviderName 属性。无法从您提供的代码中详细说明您需要的查询。

【讨论】:

  • 我试图实现此代码:我收到此错误:错误 24 'System.Collections.Generic.IEnumerable' 不包含 'ProviderName' 的定义并且找不到接受“System.Collections.Generic.IEnumerable”类型的第一个参数的扩展方法“ProviderName”(您是否缺少 using 指令或程序集引用?) C:\ TFS-Alliance\Suite\Main\Source\Core\Core\Services\EmailService.cs 88 58 Core (Common\Core\Core)
  • 您尝试实现这两个中的哪一个 - 选项 #1 或 #2?
  • 我实际上最终弄明白了......最终在我的一种数据类型中出现了错误,但我最终选择了这条路线而不是另一条路线。谢谢。
【解决方案2】:

我只是在猜测,您需要来自AddressProviders 的单个IEmailAddressesProvider,它由接口中的ProviderName 属性和变量provider 确定。

如果是这样,您可以使用 Enumerable.FirstOrDefault 返回第一个匹配的 AddressProvider 或 null 如果没有找到给定的ProviderName

// ...
ev.ViewModel.ProviderName = AddressProviders
    .FirstOrDefault(ap => ap.ProviderName == yourProviderName);
ev.ViewModel.Provider = provider;
// ...

【讨论】:

  • FirstOrDefault 到底是什么?我收到此错误:错误 322“System.Collections.Generic.IEnumerable”不包含“FirstOrDefault”的定义,并且没有扩展方法“FirstOrDefault”接受“System”类型的第一个参数.Collections.Generic.IEnumerable' 可以找到(您是否缺少 using 指令或程序集引用?) C:\TFS-Alliance\Suite\Main\Source\Core\Core\Services \EmailService.cs 87 58 Core (Common\Core\Core) 抱歉格式错误....
  • 我已经在我的回答中链接了 msdn。这是一种扩展方法,它应该适用于您的IEnumerable&lt;Alliance.Library.Email.IEmailA‌​ddressesProvider&gt;。由于您已经在使用其他 linq 方法,例如OrderBy,我想知道为什么会出现此异常。可能是因为你忘记在这个类中添加using System.Linq;了。
  • @JLott 你能确认蒂姆的猜测是正确的吗?如果是这样,您可能想更新您的问题。
  • 是的,导致 FirstOrDefaile 上的错误不是我得到的:错误 322 运算符“==”不能应用于“字符串”和“Alliance.Library.Email.IEmailSetupProvider”类型的操作数跨度>
  • @JLott:然后将provider替换为string类型的提供者的名称。你没有提到它。编辑了我的答案。
【解决方案3】:

如果您对上述答案有疑问,请尝试使用其中之一。

ev.ViewModel.ProviderName = AddressProviders.Where(p=> p.ProviderName == provider).Single();
ev.ViewModel.ProviderName = AddressProviders.Where(p=> p.ProviderName == provider).First();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多