-1

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

If you need to see anymore of my code, such as the interfaces or the viewmodel, please let me know. Any help would be appreciated!

4

3 回答 3

2

As far as your example is concerned, you can think of IEnumerable<T> as being pretty much synonymous with List<T>: it's a collection of objects; it could be just one, it could be none, it could be a hundred. There's more to IEnumerable than that, but for your purposes that's as much as you need to think about.

In this code:

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

you're asking MEF to gather all the exported implementations of IEmailAddressesProvider. What you get back is a collection of objects: even if it finds just one, you still get a collection with only one element. In this later line:

ev.ViewModel.ProviderName = AddressProviders;

I'm guessing that the left hand side is expecting a string, but the right hand side is a collection of IEmailAddressesProvider. Apart from the fact that you probably actually want the ProviderName property of the IEmailAddressesProvider and not the whole object, you also need to say which object in the collection to use. There are two ways you might deal with this:

  1. If you know that there will only be one implementation of IEmailAddressesProvider, then change ImportMany to Import like so

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

    and change that other assignment to ev.ViewModel.ProviderName = AddressProviders.ProviderName. Note that this will break as soon as you export a second implementation of IEmailAddressesProvider, so only do this if you really know there can only be one.

  2. If there may be several implementations of IEmailAddressesProvider, then you need to find the specific one you want. You would query the AddressProviders collection with something like FirstOrDefault (as the other answers have said) to find the right object and then use the ProviderName property from that result. It's not possible to say much more about the query you need from the code you've provided.
于 2013-02-05T23:42:09.433 回答
1

I'm just guessing, you want a single IEmailAddressesProvider from the AddressProviders which is determined by the ProviderName property in the interface and the variable provider.

If that is true, you can use Enumerable.FirstOrDefault which returns the first matching AddressProvider or null if no was found with the given ProviderName:

// ...
ev.ViewModel.ProviderName = AddressProviders
    .FirstOrDefault(ap => ap.ProviderName == yourProviderName);
ev.ViewModel.Provider = provider;
// ...
于 2013-02-05T21:26:28.327 回答
0

If you are having problems with the above answer try using one of these.

ev.ViewModel.ProviderName = AddressProviders.Where(p=> p.ProviderName == provider).Single();
ev.ViewModel.ProviderName = AddressProviders.Where(p=> p.ProviderName == provider).First();
于 2013-02-05T21:38:34.493 回答