C# 合成后,如何在MEF中更改部分合成?
我已将我的应用程序设置为具有可发现的安全服务(C# 合成后,如何在MEF中更改部分合成?,c#,.net,unity-container,mef,composition,C#,.net,Unity Container,Mef,Composition,我已将我的应用程序设置为具有可发现的安全服务(ISecurityService),该服务具有单个方法IPrincipal GetPrincipal())。然后,实现者可以自由决定如何获取主体(通过域登录、DB等)。因此,我的应用程序在启动时会根据用户所处的角色进行操作,例如,我导入的界面部分如下所示: [Import] public ISecurityService SecurityService { get; set; } [ImportMany] public IEnumerable
ISecurityService
),该服务具有单个方法IPrincipal GetPrincipal()
)。然后,实现者可以自由决定如何获取主体(通过域登录、DB等)。因此,我的应用程序在启动时会根据用户所处的角色进行操作,例如,我导入的界面部分如下所示:
[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);
}
}
[导入]
公共ISecurityService安全服务{
获得;设置;
}
[进口数量]
公共IEnumerable导入面板{
获得;设置;
}
公众可观察收集小组{
获得;设置;
}
公共无效OnImportsAssetized(){
面板。清除();
IPrincipal p=Thread.CurrentPrincipal;
foreach(导入面板中的ISectionPanel sp.Where(sp=>sp.RequiredRole==null | | p.IsInRole(sp.RequiredRole))){
增加(p);
}
}
不要过多地关注实现,稍后将更改为注释,然而,这里让我变得更加大胆的重要一点是,在设置安全主体之前,部件的组合已经发生了。这意味着我现在有猫捉老鼠的情况
我现在已经通过在影响链接发生的导入上使用Lazy
解决了这个问题,但是如果一个部件的另一个实现者忘记使用Lazy
,它可能会触发链接加载并导致应用程序失败
其他人用什么来克服这种情况
以前我有unity,我通过简单地使用RegisterInstance(T)
以更手动的方式控制它,现在我尝试使用“官方”MEF编写应用程序,因为这是框架附带的,我不再需要担心unity
理想情况下,我希望能够做到的是
RegisterInstance(T)
)您可以分两个阶段初始化应用程序:
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);
}
}
publicstaticvoidmain(字符串[]args)
{
使用(var container=newcompositioncontainer(…)
{
//阶段1:组合安全服务并初始化主体
var securityService=container.GetExportedValue();
securityService.InitializePrincipal();
//阶段2:编写应用程序的其余部分并启动它
var form=container.GetExportedvalue();
申请表格;
}
}
在MEF中,或多或少与注册状态相对应的是方法。如果主机在不使用MEF的情况下创建了安全服务,这将起作用。因为您仍然希望使用MEF发现安全服务,类似Wim建议的方法可能是一个很好的解决方案。我很困惑:您说您得到了主体吗来自ISecurityService.GetPrincipal()
,但您的示例代码实际上是从线程中获取的。CurrentPrincipal
。这是您问题的原因吗?不,对不起,我应该解释一下。调用我的安全服务GetPrincipal设置线程。CurrentPrincipal在应用程序启动过程中,您刚刚给了我一个灯泡时刻。来自codeplex I的所有MEF文档我想我需要调用ComposeParts()
来构建依赖关系图,但现在我想我明白了,我可以使用MEF,就像我以前调用GetExportedValue
时使用Unity来构建我的图一样,该依赖关系的任何依赖关系都将得到解决,对吧?我非常感谢您向我指出这一点,我个人认为MEF文档这一点可以大大提高:)@Brett:对GetExportedValue
的功能与Unity的Resolve
几乎相同。有点遗憾的是,方法名和文档在这方面太神秘了。这可能是因为MEF非常关注可扩展性场景(在一些关键的扩展点上调用ComposeParts
),而不是全面的依赖注入,现在我的大脑中有两个方面在为从统一走向MEF而斗争,一方试图说服另一方回到统一;)非常感谢Daniel,是的,我想我之前看到过这一点,我实际上面临的问题是我编写的安全服务也有它自己的依赖性,即IUserProvider
,这是我知道在哪里加载用户数据库的方式,如static(test)或db。我可能有点天真地认为在容器构建之后需要调用ComposeParts
,但现在我意识到情况并非如此。丹尼尔,你也帮了很多忙,真的非常感谢你。