IIS下的MEF未加载部件



我在iis下加载mef部件时遇到问题。加载方法如下:

private void LoadPlugins(string path)
{
    var aggregateCatalog = new AggregateCatalog();
    var directoryCatalogExe = new DirectoryCatalog(path, "*.exe");
    aggregateCatalog.Catalogs.Add(directoryCatalogExe);
    var container = new CompositionContainer(aggregateCatalog);
    container.ComposeParts(this);
}

该方法在控制台应用程序或cassini中运行良好。在iis下,部件计数为0-没有错误,事件日志中没有异常,什么都没有。。。

我完全不知道发生了什么。这条路是100%正确的。

我同意@stakx的意见。我使用了一种不同的方法来创建容器,使其更加不受环境影响。我创建了一个接口:

/// <summary>
/// Defines the required contract for implementing a composition container factory.
/// </summary>
public interface ICompositionContainerFactory
{
    #region Methods
    /// <summary>
    /// Creates an instance of <see cref="CompositionContainer"/>.
    /// </summary>
    /// <returns>An instance of <see cref="CompositionContainer"/>.</returns>
    CompositionContainer CreateCompositionContainer();
    #endregion
}

使用默认实现(在控制台应用程序、服务主机中工作):

public class DefaultCompositionContainerFactory : ICompositionContainerFactory
{
    #region Methods
    /// <summary>
    /// Creates an instance of <see cref="CompositionContainer"/>.
    /// </summary>
    /// <returns>
    /// An instance of <see cref="CompositionContainer"/>.
    /// </returns>
    public CompositionContainer CreateCompositionContainer()
    {
        var domain = AppDomain.CurrentDomain;
        string path = domain.BaseDirectory;
        // Use the base directory from where the application is running.
        var catalog = new DirectoryCatalog(path);
        // Create the container.
        var container = new CompositionContainer(catalog);
        return container;
    }
    #endregion
}

以及web特定的实现:

public class WebCompositionContainerFactory : ICompositionContainerFactory
{
    #region Methods
    /// <summary>
    /// Creates an instance of <see cref="CompositionContainer"/>.
    /// </summary>
    /// <returns>
    /// An instance of <see cref="CompositionContainer"/>.
    /// </returns>
    public CompositionContainer CreateCompositionContainer()
    {
        string path = HttpRuntime.BinDirectory;
        // Use the base directory from where the application is running.
        var catalog = new DirectoryCatalog(path);
        // Create the container.
        var container = new CompositionContainer(catalog);
        return container;
    }
    #endregion
}

我通过配置把它连接起来。

另一件需要考虑的事情是,您正在传递*.exe作为目录过滤器,您是否在web应用程序中使用可执行程序集?

一个可能的原因可能是path的值错误。

例如,您不应该假设当前目录将是代码的"bin"目录,因此传递"."可能是个坏主意。

如果这就是您正在做的,请尝试基于Assembly.GetExecutingAssembly().Location:指定路径

// using System.IO;
// using System.Reflection;    
string binPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LoadPlugins(binPath);

在控制台应用程序或cassini和IIS中运行时的区别在于安全上下文。

当运行控制台应用程序或cassini时,安全上下文是登录的用户,也就是您。

在IIS下运行时,安全上下文是应用程序池的标识,默认情况下为NETWORK SERVICE。

可能是您的MEF部件位于NETWORK SERVICE无法访问的目录中。

最新更新