我已将我的应用程序设置为具有可发现的安全服务 (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);
}
}
不要过于关注实现,这将在稍后更改为注释然而,让我大吃一惊的重要事情是,部件的组合是在设置安全主体之前发生的。这意味着我现在陷入了猫捉老鼠的境地。
我现在已经通过在影响链接发生的导入上使用 Lazy
解决了这个问题,但是如果部件的另一个实现者忘记使用 Lazy
它可能会触发连锁负载并导致应用程序失败。
其他人用什么来克服这样的情况?
以前,我通过简单地使用 RegisterInstance(T t)
以更手动的方式控制了 Unity,现在我尝试使用“官方”MEF 编写应用程序,因为它附带框架,我不再需要担心统一性。
理想情况下,我希望能够做的是。
- 在启动时手动创建部件之前的合成
- 创建一个合成容器,手动添加我的预构建部件(例如统一中的
RegisterInstance(T t)
)
- 使用文档中显示的常用合成方法查找剩余部件。
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 concentrate 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.
- Create parts manually at startup prior composition
- Create a composition container manually adding my pre-built parts (like
RegisterInstance<T>(T t)
in unity
- Find remaining parts using the usual methods of composition shown in the docs.
发布评论
评论(2)
您可以分两个阶段初始化应用程序:
You could initialize your application in two phases:
在 MEF 中,或多或少对应于
RegisterInstance
的是AddExportedValue
方法。如果主机在不使用 MEF 的情况下创建安全服务,则这将起作用。由于您仍然想使用 MEF 发现安全服务,像 Wim 建议的那样可能是一个很好的解决方案。In MEF, what more or less corresponds to
RegisterInstance
would be theAddExportedValue
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.