這回答這個問題是由凱文在MEF discussion list提供。事實證明,可以使用以下代碼片段從MEF ExportDefinition和ImportDefinition數據結構中提取所有必需的信息。
的第一步是將組件類型加載到目錄。然後,對目錄中的每個零件迭代導入和導出定義。導出定義只能放在類型,方法,屬性和字段(我的代碼目前忽略)上。所以要處理導出,可以使用下面的代碼。
var exports = new List<Tuple<string, MemberInfo>>();
foreach (var export in part.ExportDefinitions)
{
var memberInfo = ReflectionModelServices.GetExportingMember(export);
Tuple<string, MemberInfo> exportDefinition = null;
switch (memberInfo.MemberType)
{
case MemberTypes.Method:
exportDefinition = new Tuple<string, MemberInfo>(export.ContractName, memberInfo.GetAccessors().First() as MethodInfo);
break;
case MemberTypes.NestedType:
case MemberTypes.TypeInfo:
exportDefinition = new Tuple<string, MemberInfo>(export.ContractName, memberInfo.GetAccessors().First() as Type);
break;
case MemberTypes.Property:
// this is a bit ugly because we assume that the underlying methods for a property are named as:
// get_PROPERTYNAME and set_PROPERTYNAME. In this case we assume that exports always
// have a get method.
var getMember = memberInfo.GetAccessors().Where(m => m.Name.Contains("get_")).First();
var name = getMember.Name.Substring("get_".Length);
var property = getMember.DeclaringType.GetProperty(name);
exportDefinition = new Tuple<string, MemberInfo>(export.ContractName, property);
break;
default:
throw new NotImplementedException();
}
exports.Add(exportDefinition);
}
爲了處理的進口,這隻能放置在性質,參數和字段(其再次忽略)以下代碼可用於:
public void ExtractImports()
{
var imports = new List<Tuple<string, string>>();
foreach (var import in part.ImportDefinitions)
{
SerializedImportDefinition importDefinition = !ReflectionModelServices.IsImportingParameter(import)
? importDefinition = CreatePropertyImport(import)
: importDefinition = CreateConstructorParameterImport(import);
}
}
private Tuple<string, string> CreatePropertyImport(ImportDefinition import)
{
var memberInfo = ReflectionModelServices.GetImportingMember(import);
if (memberInfo.MemberType != MemberTypes.Property)
{
throw new ArgumentOutOfRangeException("import");
}
// this is a bit ugly because we assume that the underlying methods for a property are named as:
// get_PROPERTYNAME and set_PROPERTYNAME. In this case we assume that imports always
// have a set method.
var getMember = memberInfo.GetAccessors().Where(m => m.Name.Contains("set_")).First();
var name = getMember.Name.Substring("set_".Length);
var property = getMember.DeclaringType.GetProperty(name);
return new Tuple<string, string>(import.ContractName, property.ToString());
}
private Tuple<string, string> CreateConstructorParameterImport(ImportDefinition import)
{
var parameterInfo = ReflectionModelServices.GetImportingParameter(import);
return new Tuple<string, string>(import.ContractName, parameterInfo.Value.ToString());
}
注意,似乎導入不能通過方法參數提供,所以上面的代碼不支持這些。
一旦所有的出口和進口都已經被處理是序列化存儲MemberInfo對象轉換成字符串格式的一個簡單的問題。
非常好的工作。我前段時間正在尋找類似於我的一些問題中看到的類似內容,很快我會再次訪問此功能。感謝分享並花時間回答你自己的問題。 –
'memberInfo'來自'memberInfo.GetAccessors()'哪裏? – l33t
@ l33t我更新了代碼示例以包含獲取'memberInfo'對象的部分。我希望這更清楚。感謝您指出缺少的代碼行。 – Petrik