如何在成分后改变MEF中的部分成分?

时间:2011-04-13 10:02:18

标签: c# .net unity-container mef composition

我已将我的应用设置为具有可发现的安全服务(ISecurityService),该服务具有单个方法IPrincipal GetPrincipal()。实施者可以自由决定如何获得委托人(通过域名登录,数据库等)。所以我的应用程序然后有部分在启动时根据用户所处的角色做事情,例如我导入的界面部分如下:

[Import]
public ISecurityService SecurityService {
    get; set;
}
[ImportMany]
public IEnumerable<ISectionPanel> ImportedPanels {
    get; set;
}
public ObservableCollection<ISectionPanel> Panels {
    get; set;
}
public void OnImportsSatisfied() {
    Panels.Clear();
    IPrincipal p = Thread.CurrentPrincipal;
    foreach (ISectionPanel sp in ImportedPanels.Where(sp => sp.RequiredRole == null || p.IsInRole(sp.RequiredRole))) {
        Panels.Add(p);
    }
}

不要过于专注于实现,这将在以后改为注释,然而,这使得我作为一个gutser的重要事情是部件的组成发生在安全主体设置之前。这意味着我现在有猫捉老鼠的情况。

我现在通过在导入时使用Lazy<T>来解决这个问题,这会影响链接,但是如果某个部分的另一个实现者忘记使用Lazy<T>,它可能会触发链式加载并导致应用失败。

其他人用什么来克服这种情况?

之前我通过简单地使用RegisterInstance<T>(T t)以更加手动的方式控制了团结,我现在尝试使用“官方”MEF编写应用程序,因为这带有框架,我不再需要担心团结。

理想情况下,我希望能够做到的是。

  1. 在合成前启动时手动创建零件
  2. 创建一个合成容器,手动添加我预构建的部分(如RegisterInstance<T>(T t) in unity
  3. 使用文档中显示的常用合成方法查找剩余部分。

2 个答案:

答案 0 :(得分:4)

您可以分两个阶段初始化您的应用程序:

public static void Main(string[] args)
{
    using (var container = new CompositionContainer(...))
    {
        // phase 1: compose security service and initialize principal
        var securityService = container.GetExportedValue<ISecurityService>();
        securityService.InitializePrincipal();

        // phase 2: compose the rest of the application and start it
        var form = container.GetExportedvalue<MainForm>();
        Application.Run(form);
    }
}

答案 1 :(得分:2)

在MEF中,与RegisterInstance或多或少相对应的是AddExportedValue方法。如果主机在不使用MEF的情况下创建安全服务,这将起作用。由于您仍然希望通过MEF发现安全服务,Wim建议的可能是一个很好的解决方案。