ExportFactory in .NET 4.0 (MEF2 Preview1)

Jul 23, 2010 at 11:20 AM
Edited Jul 23, 2010 at 11:26 AM
Hi,

I'm trying to get to grips with the ExportFactory and am struggling to get anything going. I've added the reference to the codeplex version, defined a simple interface:

	public interface ILogger
	{
		void Log(string message);
		string Name
		{
			get;
			set;
		}
	}
Realised it:

	[Export(typeof(ILogger))]
	public class ConsoleLogger : ILogger
	{
		#region Implementation of ILogger

public void Log(string message) { Console.WriteLine(string.Format("ConsoleLogger({0}) - {1}", Name, message)); } public string Name { get; set; } #endregion }

In my main class (decorated with an [Export], added an import:
[Import(typeof(ILogger)]
private ExportFactory<ILogger> loggers { get; set; }
And am trying to set up the catalog/batch:
AssemblyCatalog cat = new AssemblyCatalog(typeof(Program).Assembly);
container = new CompositionContainer(cat);
CompositionBatch batch = new CompositionBatch();
batch.AddPart(this);
container.Compose(batch);
I get a TypeLoadException on the last line above:
Could not load type 'System.ComponentModel.Composition.ExportFactory`1' from assembly 
'System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
Stack-trace:
	at System.Signature.GetSignature(SignatureStruct& signature, Void* pCorSig, Int32 cCorSig, RuntimeFieldHandleInternal fieldHandle, IRuntimeMethodInfo methodHandle, RuntimeType declaringType)
	at System.Signature..ctor(IRuntimeMethodInfo methodHandle, RuntimeType declaringType)
	at System.Reflection.RuntimeMethodInfo.get_Signature()
	at System.Reflection.RuntimeMethodInfo.get_ReturnType()
	at System.ComponentModel.Composition.ReflectionModel.ReflectionProperty.get_ReturnType()
	at System.ComponentModel.Composition.AttributedModel.AttributedModelDiscovery.GetImportDefinitionCreationInfo(ReflectionItem item, ICustomAttributeProvider attributeProvider)
	at System.ComponentModel.Composition.AttributedModel.AttributedModelDiscovery.CreateMemberImportDefinition(MemberInfo member, ICompositionElement origin)
	at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.GetImportDefinitions()
	at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.DiscoverExportsAndImports()
	at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.GetExports()
	at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePartDefinition.get_ExportDefinitions()
	at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePart.get_ExportDefinitions()
	at System.ComponentModel.Composition.Hosting.ComposablePartExportProvider.<Recompose>b__4(ComposablePart part)
	at System.Linq.Enumerable.<SelectManyIterator>d__14`2.MoveNext()
	at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
	at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
	at System.ComponentModel.Composition.Hosting.ComposablePartExportProvider.Recompose(CompositionBatch batch, AtomicComposition atomicComposition)
	at System.ComponentModel.Composition.Hosting.ComposablePartExportProvider.Compose(CompositionBatch batch)
	at System.ComponentModel.Composition.Hosting.CompositionContainer.Compose(CompositionBatch batch)
	at MEF2.Program..ctor() in C:\MyDevelopment\Development\MEF2\MEF2\Program.cs:line 27
	at MEF2.Program.Main(String[] args) in C:\MyDevelopment\Development\MEF2\MEF2\Program.cs:line 33
	at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
	at System.AppDomain.nExecuteAssembly(RuntimeAssembly assembly, String[] args)
	at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
	at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
	at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
	at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
	at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
	at System.Threading.ThreadHelper.ThreadStart()
Any clues to what I'm doing wrong? I was hoping that at this point I should be able to inspect the "loggers" property and see the registered loggers!

Regards,
Ray

Jul 23, 2010 at 1:51 PM
Edited Jul 23, 2010 at 1:53 PM

The exception message shows that the application is looking for the type ExportFactory in the assembly "System.ComponentModel.Composition". This is an assembly included in .NET 4 which does not contain ExportFactory. The correct assembly name would be "System.ComponentModel.Composition.Codeplex".

 

Since the .NET 3.5 dll is also called "System.ComponentModel.Composition" and does contain ExportFactory, it looks like you are mixing the two somehow: you're building against the .NET 3.5 codeplex version but running against the .NET 4.0 framework version of that DLL.

 

 

Jul 23, 2010 at 2:05 PM
Just checked and I'm definitely referencing the assembly "System.ComponentModel.Composition.Codeplex" at version 4.0.0.1 (runtime version v4.0.30319).

Whilst the solution was previously .NET 4.0 Client Profile, I get the same results when using the full blown .NET 4.0.

Jul 23, 2010 at 2:10 PM
Edited Jul 23, 2010 at 2:13 PM
I'm wondering whether the version distributed has a fault. I've added the "ComponentModel-v40" project into my solution, removed the CodePlex reference and added a cross-solution project reference and the exception has now gone.

<strike>Unfortunately my 'loggers' is null, but at least it feels like progress now!</strike>Working now, I had two exports and allow-default set to true in my test app!

Aug 27, 2010 at 6:45 PM

I am experiencing the exactly same problem: It seems that .Net ignores my more specific 4.0.0.1 Version and instead loads the "usual" runtime.

When I check the property tab of the assembly reference it assures me it will use version 4.0.0.1, but at runtime I get the following exception:

System.TypeLoadException: Could not load type 'System.ComponentModel.Composition.ExportFactory`2' from assembly 'System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.

How can I "override" the Assembly loading? CopyLocal is already set to true and setting "Specific Version" to true results in the assembly reference not being resolved during compilation.

Oct 8, 2010 at 12:18 AM

I am running into the same issue. How did you guys resolve this problem?

Oct 8, 2010 at 8:53 AM

I personally couldn't. But I heard from a coworker that he could resolve it by installing the assembly into the GAC.

Oct 8, 2010 at 9:28 AM

I recompiled from the source and it worked.

Oct 20, 2010 at 1:05 AM

Could you give it a try with the newest drop?

Thanks