많은 조사에서 MEF에서 인스턴스 작성 프로세스와 구성 프로세스를 분리 할 수없는 것 같아서이 문제점에 대한 내 자신의 접근 방식을 만들어야했습니다. 이 솔루션에서는 scanning of plugins이 유형, 가져 오기 및 내보내기 데이터가 어떻게 든 저장되어 있다고 가정합니다.
부품을 작성하려면 각 부품 인스턴스를 추적하고 다른 부품 인스턴스에 연결하는 방법을 기억해야합니다. 이를 수행하는 가장 간단한 방법은 가져 오기가 어떤 내보내기에 연결되어 있는지 추적하는 그래프 데이터 구조를 사용하는 것입니다.
public sealed class CompositionCollection
{
private readonly Dictionary<PartId, PartDefinition> m_Parts;
private readonly Graph<PartId, PartEdge> m_PartConnections;
public PartId Add(PartDefinition definition)
{
var id = new PartId();
m_Parts.Add(id, definition);
m_PartConnections.AddVertex(id);
return id;
}
public void Connect(
PartId importingPart,
MyImportDefinition import,
PartId exportingPart,
MyExportDefinition export)
{
// Assume that edges point from the export to the import
m_PartConnections.AddEdge(
new PartEdge(
exportingPart,
export,
importingPart,
import));
}
}
두 부분을 연결하기 전에 가져 오기를 내보내기에 연결할 수 있는지 확인해야합니다. 다른 경우에는 MEF가 그렇게하지만이 경우에는 스스로해야합니다. 그 접근하는 방법의 예는 다음과 같습니다 가져 오기 유형이 조금 까다로운 일이 될 수있는 일반적인 유형을 기반으로하는 경우 특별한 경우 (같은 IEnumerable<T>
, Lazy<T>
등) 결정을 필요로
public bool Accepts(
MyImportDefinition importDefinition,
MyExportDefinition exportDefinition)
{
if (!string.Equals(
importDefinition.ContractName,
exportDefinition.ContractName,
StringComparison.OrdinalIgnoreCase))
{
return false;
}
// Determine what the actual type is we're importing. MEF provides us with
// that information through the RequiredTypeIdentity property. We'll
// get the type identity first (e.g. System.String)
var importRequiredType = importDefinition.RequiredTypeIdentity;
// Once we have the type identity we need to get the type information
// (still in serialized format of course)
var importRequiredTypeDef =
m_Repository.TypeByIdentity(importRequiredType);
// Now find the type we're exporting
var exportType = ExportedType(exportDefinition);
if (AvailableTypeMatchesRequiredType(importRequiredType, exportType))
{
return true;
}
// The import and export can't directly be mapped so maybe the import is a
// special case. Try those
Func<TypeIdentity, TypeDefinition> toDefinition =
t => m_Repository.TypeByIdentity(t);
if (ImportIsCollection(importRequiredTypeDef, toDefinition)
&& ExportMatchesCollectionImport(
importRequiredType,
exportType,
toDefinition))
{
return true;
}
if (ImportIsLazy(importRequiredTypeDef, toDefinition)
&& ExportMatchesLazyImport(importRequiredType, exportType))
{
return true;
}
if (ImportIsFunc(importRequiredTypeDef, toDefinition)
&& ExportMatchesFuncImport(
importRequiredType,
exportType,
exportDefinition))
{
return true;
}
if (ImportIsAction(importRequiredTypeDef, toDefinition)
&& ExportMatchesActionImport(importRequiredType, exportDefinition))
{
return true;
}
return false;
}
하는 것으로.
일단 모든 구성 정보가 저장되면 필요한 모든 정보를 사용할 수 있기 때문에 언제든지 파트의 인스턴스화를 수행 할 수 있습니다. 인스턴스화는 신뢰할 수있는 Activator 클래스의 사용과 함께 반영에 대한 관대 한 도움이 필요하며 독자에게 연습으로 남겨 둡니다.
게으른 클래스를 찾고 계십니까? 이 기사의 '지연 인스턴스 생성'섹션을 참조하십시오. http://www.codeproject.com/Articles/376033/From-Zero-to-Proficient-with-MEF –
burnttoast11
아니요'게으른'이 (내가) 찾고있는 것이 아닙니다. 에 대한. 불행히도'Lazy '을 사용하려면'T'를 포함하는 어셈블리가로드되어 있어야합니다. 내가 원하는 것은 플러그인 어셈블리를로드 할 필요없이 파트를 작성하는 방법입니다. 부품의 생성 (즉, 실제 객체 생성)은 다른 시간/장소에서 발생합니다. 플러그인 어셈블리는 생성 시간/장소까지로드되지 않아야합니다. –
Petrik