使用IEnumerable<>并使用其类型创建属性

时间:2013-02-05 21:10:47

标签: c# linq interface viewmodel ienumerable

我没有使用过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"; }
    }
}

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

3 个答案:

答案 0 :(得分:2)

就您的示例而言,您可以认为IEnumerable<T>几乎与List<T>同义:它是对象的集合;它可能只是一个,也可能是一个,它可能是一百个。 IEnumerable比{I}更多,但出于您的目的,您需要考虑的事情。

在此代码中:

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

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

ev.ViewModel.ProviderName = AddressProviders;

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

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

    Import

    并将其他作业更改为[Import] public IEmailAddressesProvider AddressProviders { get; set; } 。请注意,一旦导出ev.ViewModel.ProviderName = AddressProviders.ProviderName的第二个实现,这将会中断,所以只有在您确实知道只有一个实现时才会这样做。

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

答案 1 :(得分:1)

我只是在猜测,您需要IEmailAddressesProvider中的AddressProvidersProviderName,该provider由界面中的null属性和变量ProviderName确定。

如果确实如此,您可以使用Enumerable.FirstOrDefault返回第一个匹配的AddressProvider,如果找不到给定的// ... ev.ViewModel.ProviderName = AddressProviders .FirstOrDefault(ap => ap.ProviderName == yourProviderName); ev.ViewModel.Provider = provider; // ... ,则返回{{1}}:

{{1}}

答案 2 :(得分:0)

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

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