MEF 错误消息 - VS2010

MEF Error message - VS2010

谁能帮我解释这个错误消息:

system.componentmodel.composition.changerejectedexception

The composition remains unchanged. The changes were rejected because of the following error(s): The composition produced a single composition error. 
The root cause is provided below. Review the CompositionException.Errors property for more detailed information.

1) No exports were found that match the constraint: 
ContractName    Itok.BusinessLogic.Interfaces.IFolderService
RequiredTypeIdentity    Itok.BusinessLogic.Interfaces.IFolderService

Resulting in: Cannot set import 'Itok.Web.Photos.Presenters.DefaultPresenter._folderService (ContractName="Itok.BusinessLogic.Interfaces.IFolderService")' on part 'Itok.Web.Photos.Presenters.DefaultPresenter'.

Element: Itok.Web.Photos.Presenters.DefaultPresenter._folderService (ContractName="Itok.BusinessLogic.Interfaces.IFolderService") --> Itok.Web.Photos.Presenters.DefaultPresenter

这里是 IFolderService.cs:

using System;
using System.Collections.Generic;
using Itok.Entities;

namespace Itok.BusinessLogic.Interfaces
{
    public interface IFolderService
    {
        List<Folder> GetFriendsFolders(Int32 AccountID);
        void DeleteFolder(Folder folder);
        List<Folder> GetFoldersByAccountID(Int32 AccountID);
        Folder GetFolderByID(Int64 FolderID);
        Int64 SaveFolder(Folder folder);
    }
}

这是导出 class 定义,FolderService.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Itok.BusinessLogic.Interfaces;
using System.ComponentModel.Composition;
using Itok.DataAccess.Interfaces;
using Itok.Common;
using Itok.DataAccess;
using Itok.Interfaces;
using Itok.Entities;

namespace Itok.BusinessLogic
{    
    [Export(typeof(IFolderService))]    
    [Export(typeof(ICache))]
    public class FolderService : IFolderService
    {
        [Import]
        private IFriendRepository _friendRepository;
        [Import]
        private IFolderRepository _folderRepository;
        [Import]
        private ICache _cacheService;

        public FolderService()
        {
            MEFManager.Compose(this);
        }

        public List<Folder> GetFriendsFolders(Int32 AccountID)
        {
            List<Friend> friends = _friendRepository.GetFriendsByAccountID(AccountID);
            List<Folder> folders = _folderRepository.GetFriendsFolders(friends);
            folders.OrderBy(f => f.CreateDate).Reverse();
            return folders;
        }

         public void DeleteFolder(Folder folder)
        {   
            if (_cacheService.Exists(folder.AccountID.ToString()))
            {
                _cacheService.Delete(folder.AccountID.ToString());
            }

            _folderRepository.DeleteFolder(folder);
        }

        public List<Folder> GetFoldersByAccountID(int AccountID)
        {        
            List<Folder> cachedFolders = _cacheService.Get(AccountID.ToString()) as List<Folder>;
            if (cachedFolders != null)
            {
                return cachedFolders;
            }
            else
            {
                cachedFolders = _folderRepository.GetFoldersByAccountID(AccountID);
                _cacheService.Set(AccountID.ToString(), cachedFolders);
                return cachedFolders;
            }
        }

        public Folder GetFolderByID(Int64 FolderID)
        {
            return _folderRepository.GetFolderByID(FolderID);
        }

        public Int64 SaveFolder(Folder folder)
        {
            return _folderRepository.SaveFolder(folder);
        }
    }
}

首先感谢您为我节省了时间。

该错误消息表示 MEF 正在寻找使用接口 IFolderService 导出的 class,但容器中没有。

要对此进行调查,首先检查是否有一个 class 导出该接口,如果有,然后查看 class 是否被容器拾取,第三,如果这些都不能解决问题,请查看使用接口 IFolderService 导出的 class 是否有其他一些无法满足的导入。

终于,我找到了问题的解决方案。它与 MEF 指向的 IFolderService 没有直接关系。该应用程序依赖于业务逻辑中的组件 (FolderService),而该组件又依赖于接口 ICache 和实现包装器 Cache.cs。由合同名称 Itok.Interfaces.ICache 指定的 ICache 已被导出四次(仅一次导入)。当我试图扩展解决方案时,这没有引起注意。 MEF 无法判断要使用哪个导出。真正的问题是 MEF 指向 class 链上两层!

感谢 TomDoesCode 查看问题,我希望这对遇到类似问题的其他人有所帮助。

这个问题的长期解决方案是,如果您有许多满足导入的导出,您可能有两个选择:

I) 将 [Import] 更改为 [ImportMany]。然后在运行时,决定为合约使用哪个导入。问问自己是只挑选第一个可用的,还是一次随机使用一个。

II) 结合元数据使用 [ImportMany] 来决定使用哪个导入。