MEF Container cannot compose parts from Shared Assembly - c#

I have 3 projects in my solution:
1- ExporterLib (Class Library)
2- ImporterApp (WPF Application)
3- SharedLib (Class Library)
the first two projects reference "SharedLib" which contains an interface called ISharedClass .
Inside "ImporterApp" I have a class called ClassA:
public class ClassA
{
[Import] private ISharedClass part;
}
Inside "ExporterLib" I have a class called SharedClassExport:
[Export(ISharedClass)]
public class SharedClassExport : ISharedClass
{
//....
}
In ImporterApp I use a DirectoryCatalog referencing ExporterLib.dll file and a container. But when I try to compose the parts of ClassA instance using the container I receive an exception saying:
1) No exports were found that match the constraint:
ContractName SharedLib.ISharedClass
RequiredTypeIdentity SharedLib.ISharedClass
When I use the debugger to see the parts inside the catalog I see the correct SharedClassExport Part, but it's not referencing ISharedClass!
What Should I Do?
P.S. : I want to use MEF and I don't want to merge any of these projects together.
Thanks in advance.
SUMMARY:
//Specifying the contract type may be important if
you want to export a type other then the base type,
such as an interface.
https://msdn.microsoft.com/en-us/library/system.componentmodel.composition.importattribute(v=vs.110).aspx

Please try using [Export(typeof(ISharedClass))] . If you are exporting a type other than a base type, such as interface, it is important to specify the full contract type using typeof. To match the export use [Import(typeof(ISharedClass))]. Please let me know if this worked if not please provide the DirectoryCatalog composition logic you are using?

Check the bin folder of ImporterApp after your build. I'm willing to wager that ExporterLib.dll is not in the folder. Since ExporterLib.dll is not a direct dependency of ImporterApp MSBuild doesn't copy it to ImporterApp's bin folder on build. To fix this you have a few choices:
You can add a reference to ExporterLib in the ImporterApp project.
If you don't want to add the reference, a post build step on ImporterApp to copy the ExporterLib.dll to the bin directory of ImporterApp would also work.
You could also setup each project to build to the same directory in the solution structure.

Related

How to separate Class Library into multiple assembly (*.dll)?

I build a class library project with separate class by folder.
Example:
TEST
Security
Converter
Utility
After I compile project, I will have TEST.dll
but I want TEST.dll, TEST.Security.dll, TEST.Converter.dll, & TEST.Utility.dll
Note: Security, Converter, Utility is folder in TEST project. In each folder have c# class.
How to do?
Create separate projects for each
Example:
name project TEST.Security class library
name project TEST.Converter class library
name project TEST.Utility class library
the fact that you separate classes by folders means nothing when it comes to the dll output.
If you want one dll per folder then you will have to create one separate class library project for each one. In the properties of each project you can set the name of the dll file itself.
This being said, the name of the dll is less important, it's the namespaces that will matter. The namespace is set in each class file and this will affect your "using" statements.

Adding references for code moved into a class library

From a solution, which I made in Visual Studio 2013, I want to transfer a method to a DLL (class library project).
When I paste the method in the DLL project, it doesn't recognize parts of the code and it's showing this error`:
"are you missing a using directive or an assembly reference?"
Because of that, the DLL can't be built. I am assuming, that a certain reference to the solution is required, but I am not sure how to proceed.
I know how to add a reference from a solution to a DLL, but I'm not sure how it's done the other way around or even if it's possible.
You can't add reference to EXE from class library (assuming EXE uses that class library) as it will introduce circular reference.
Usually you need to refactor all dependencies so class library either have them all or allow application to inject dependencies from EXE/other clients. In later case class library needs to define base classes/interfaces to allow such injection.
Yes, you need to restore the same references that the original project uses, if they are used in the code you want to move.
If you need to do this by hand (i.e. without tools like ReSharper):
Move the code to the new assembly.
For each namespace or type giving the error, find it in the Object Browser.
Locate the assembly containing that namespace and type, and add a reference to that assembly in your new project.
You may also have to add a Project Reference to the original project.

Creating libraries that need reference to main program

I have a build engine which I am adding customisation to.
The customisation I am adding is in the form of a library which contains functions specific to Subversion.
My problem is, now I have separated this functionality into a main exe and several dll's, this dll requires a reference to some of the classes inside the main project (exe).
For example:
My Build Engine program contains a 'Project Class'.
The SVN dll has a function with signature:
SVNSourceControl(Project project, Logger logger)
I instantiate the SVN class with a reference to the Project I build as well as a Logger that carries out the logging for me.
The logger is fine as I have separated that into another dll and added references.
Do I need to separate my 'project' class into a separate dll and add references?
Do I need to add a reference to my dll which is the reference to my main exe and the classes within it?
Do I need to re-code the library to get round it some how? (Hopefully not :))
Thanks.
One thing you could do would be to create an interface for your Project class that exposes the parts of Project that you need access to in your library:
public interface IProject
{
string Name { get; }
}
Then change your SVNSourceControl() method to accept the interface instead of the class:
SVNSourceControl(IProject project, Logger logger)
Once that's done, all that's left is to define Project in your main exe as implementing IProject:
public class Project : myDllNamespace.IProject
{
public string Name { get; private set; }
// Whatever else
}
This is assuming that the dll containing the IProject interface and SVNSourceControl() method are already added as a reference to the main dll. If that's not true, you'll have to do that as well.

Pass class object to different dll

I have a little problem understanding what I should do.
I have a main project MainProj.
And another project called PluginHandler who has an IPlugin interface.
What I'm trying to achieve is to "send" an object called Network from MainProj to each plugin that implement the IPlugin interface.
My problem is what type should I write in the IPlugin, because it's in a different project I can't just say Network - and I can't reference it because I need a reference to the PluginHandler in the MainProj, in order to instantiate each plugin (using reflections)
Any ideas?
You need to create a "shared library". So instead of
MainProj
Network
PluginHandler
IPlugin
Plugin
you should have
MainProj
PluginHandler
IPlugin
Plugin
Common
Network
So you place the Network class inside the Common project and reference this by all other projects.
You just need to add the other project as a reference in your MainProj
and then add a using statement to import that namespace into your file.
When adding a reference you can either choose a dll or just choose another project.
How to add a reference
How to add a using statement

Is it possible to have sub namespaces in the same dll?

I am creating a dll project. In this project I have a main namespace, for example myClasses. In this project, I create a new folder, myClasses2, so I have a second namespace, myClasses.myClasses2. When I create the dll, I get the myClasses.dll.
In other project, for example in a WPF project, I add a reference to this dll, and I can do "using myClasses" but I can't do "using myClasses.myClasses2" so I can't use this second group of classes.
There is any way to have, in one dll, the two namespaces? I would like to avoid to have two separate dlls, one for myClasses and other for myClasses2.
EDIT1: Thanks to all. The problem is that the classes are not public. I use the default when add a new class. When I set the class as public and generate again, I can using the second namespace.
Thanks.

Categories