使用IEnumerable<>;以及创建具有其类型的属性

本文关键字:属性 创建 类型 lt IEnumerable gt 使用 | 更新日期: 2023-09-27 17:57:43

我很少使用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"; }
    }
}

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

使用IEnumerable<>;以及创建具有其类型的属性

就您的示例而言,您可以将IEnumerable<T>视为List<T>的同义词:它是对象的集合;可能只有一个,也可能没有,也可能有一百个。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; }
    

    并且将该另一个指派改变为CCD_ 12。请注意,一旦导出IEmailAddressesProvider的第二个实现,这种情况就会中断,所以只有在您真的知道只能有一个实现的情况下才能这样做。

  2. 如果IEmailAddressesProvider可能有几个实现,那么您需要找到您想要的特定实现。您可以使用类似FirstOrDefault的内容查询AddressProviders集合(正如其他答案所说),以找到正确的对象,然后使用该结果中的ProviderName属性。从您提供的代码中不可能对您需要的查询有更多的了解

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

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

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

如果您对上面的答案有问题,请尝试使用其中一个。

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