我有一个应用程序,我正在使用MEF来编写它。我想知道是否可以在导入部件后更新部件的元数据信息。
执行此操作的原因如下:我在ListBox中显示导入的部件名称和typeof(int)属性,并且在选择相应的ListBoxItem之前不会加载它们(非常标准)。现在我想在某个事件引发时更新一个部件的元数据信息,因此ListBox中显示的信息类似于“[部件名称]([新数字])”。
我将元数据导入为定义其信息的接口,但是当我将int属性设置为可编辑(使用set accesor)时,我在合成时收到以下execption:
"The MetadataView 'myMetadataInterface' is invalid
because property 'myInt' has a property set method."
有没有办法实现这个目标?或者,只有在创建零件后才能读取元数据?
我知道这个问题看起来很奇怪,但它并没有让它变得那么困难,因此也很有趣; - )
我只是想知道在组成部件之后但在实际加载之前是否可以更新元数据属性(HasValue == false)。不要担心过滤或找到零件。
我在导出接口中添加了一个属性,该属性仅用于在UI中表示并且要更新,此属性没有其他功能,并且部件不会被它过滤。
由于
答案 0 :(得分:3)
元数据过滤和DefaultValueAttribute
指定元数据视图时,将进行隐式过滤 仅匹配包含定义的元数据属性的导出 在视图中。您可以在元数据视图上指定属性 不需要,使用 System.ComponentModel.DefaultValueAttribute。下面你可以看到哪里 我们在IsSecure上指定了默认值false。这意味着如果 部件导出IMessageSender,但不提供IsSecure元数据, 然后它仍将匹配。
短版(在问题编辑后编辑)。
您不应该在运行时更新元数据。如果您有一些应该更新并且属于mef部分的数据,则需要选择通过重新编译来更新它,或者将该数据存储在dll之外的灵活存储中。没有重新编译就没有办法存储你在dll中所做的更改,所以这是一个有缺陷的设计。
上一篇文章。
通过说明加载的组件,改变视图上的值。确定元数据只是返回初始化值的对象的接口;确保您可以在技术上更新这些值,但这不是元数据的目的。
您不会更改Name
实例的Type
字段。为什么不?因为它是元数据。在运行时更新元数据意味着以某种方式修改了实际数据实例的性质。
如果可能,这行代码不会引入Triple类型。
typeof(Double).Name = "Triple";
var IGotATriple = new Triple();
如果要更改值,则需要使用该信息创建另一个对象并绑定到该对象。编译元数据。如果在加载零件后更改它,它不会更改零件源中的任何内容,因此您将撒谎。 (除非您将访问源代码并在那里进行更改并重新编译)。
让我们看一个例子:
[Export(typeof(IPart))]
[ExportMetadata("Part Name","Gearbox")]
[ExportMetadata("Part Number","123")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class GearBoxPart : Part { public double GearRatio ... }
现在,我们假设您有一个显示可用部件及其编号的UI。现在,制造商出于任何原因更改了部件号,并且您想要更新它。如果可以,您可能需要考虑将部件号存储在清单或数据库中。或者,每次零件号更改时,您都必须重新编译。
可以重新编译。您有一个执行上述操作的控制器UI,但您不是更新元数据,而是提交重建部件代码文件的请求。该请求将通过解析代码文件,替换部件号,然后发送批量重新编译并重新分发新的dll来处理。这是IMO的大量工作。
因此,您设置了一个数据库。然后将对象元数据更改为此。
[ExportMetadata("OurCompanyNamePartNumber","123")]
然后您有一个数据库/ manifest / xml,它将您公司设计的唯一永久静态部件号映射到当前部件号。控件UI中的修改会更新database / manifest / xml。
<PartMap>
<PartMapEntry OurCompanyNamePartNumber="123" ManufacturerPartNumber="456"/>
...
</PartMap>
然后,最终用户UI按制造商部件号查找零件,mef代码在PartMap中查找以获取零件编号。