开发者

How can I change part of the composition in MEF after composition?

I've setup my app to have a discoverable security service (ISecurityService) which has a single method IPrincipal GetPrincipal(). Implementers are free to then decide how to get the principal (via domain login, DB etc..). So my app then has parts which do things on startup determined on the roles the user is in, for one example I sections of the interface imported like so:

[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);
    }
}

Don't co开发者_开发问答ncentrate too much on the implementation, this is going to change to annotations later, however, the important thing here that made me crop a gutser was that composition of parts was occurring PRIOR to the security principal being set. What this means is I now have a cat and mouse situation.

I've now solved this by using Lazy<T> on imports which affected the chaining to occur, however if another implementer of a part forgets to use Lazy<T> it may trigger a chained load and cause the app to fail.

What have others used to overcome scenarios such as this?

Previously I had unity which I controlled in a more manual way by simply using RegisterInstance<T>(T t), I've trying to now write apps using the "official" MEF as this comes with the framework and I no longer need to worry about unity.

Ideally what I'd like to be able to do is.

  1. Create parts manually at startup prior composition
  2. Create a composition container manually adding my pre-built parts (like RegisterInstance<T>(T t) in unity
  3. Find remaining parts using the usual methods of composition shown in the docs.


You could initialize your application in two phases:

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);
    }
}


In MEF, what more or less corresponds to RegisterInstance would be the AddExportedValue method. This would work if the host created the security service without using MEF. Since you still want to discover the security service with MEF, something like Wim suggests is probably a good solution.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜