I wrote a dlls that connect to some 3rd party API, each DLL has the methods: SignIn,Upload,Download,SignOut.
My manager asked me to implement a factory pattern because in future I will write more dlls to other APIs that has the same methods signuture.
For now I have:
DLL 1: OneDrive
It has a class with methods: SignIn,Upload,Download,SignOut.
So if I want to use it I'm adding reference to this DLL and then any app can use this DLL.
DLL 2: DropBox
It has also class with methods: SignIn,Upload,Download,SignOut.
My question: How do I implement the factory method design pattern in this secnario?
What I did: I created another DLL("The new DLL") this DLL would contain the "FactoryClass", the problem is that the creator in this dll should return a type of "OneDrive" or "DropBox" that means I should add refernce to the first two dlls ("OneDrive" and "DropBox").
But, The classes "OneDrive" and "DropBox" should implement some abstrct class whithin the new dll that means I should add refernce to the new dll.
but it's not possible because it's circular dependency (Visual studio error)
In order to eliminate the circular dependencies, you must keep the dependencies in the direction of your main assembly.
This is in partly solved by an interface (or abstract class) declared in this central assembly, but there is the additional problem of instantiating the concrete implementations without directly referencing the dependencies.
This can be solved by allowing your factory to keep a registry of available implementations. You can find an example of a simple factory with registration in this other stack overflow question
Related
I am developing a C# desktop application that should try to find and consume a plugin hosted in a totally different C# project so that the application does not know anything of the plugin host project and its types.
If the plugin DLL is found in my application EXE folder, I should be able to create an instance of the plugin interface. But to do so in the application, I would need to make the plugin assembly known to the application solution at compilation time, which is not permissible due to the project management issues.
The only way to do it, as far as I can see, is to have two assemblies: the one with the interface only, which can be added to the application solution, and the other one with the plugin implementation.
But is there a possibly more elegant solution?
The only way to do it, as far as I can see, is to have two assemblies: the one with the interface only, which can be added to the application solution, and the other one with the plugin implementation
This is the solution I have used for plugins. The interface project is hosted in the main application solution, with the interface dll either manually copied to the plugin solution, or referenced thru nuget. I'm not aware of any solution that is more elegant.
Changes to the interface will be slightly cumbersome, but this is not necessarily a bad thing since frequent changes to public APIs can be difficult for the user of the API. It is a good idea to have some plan for how different API versions should be handled by the plugin implementation. For example by exposing a version property in the interface that can be used to determine what methods are safe to call or not.
TL:DR How do I reference an assembly only in a class library rather than both the library and the calling project?
I am building a utility library in C# in order to promote code reuse. In this instance, I am wanting to do something things with a TFS server and need to reference several assemblies from the TFS side of things:
Microsoft.TeamFoundation.Client
Microsoft.VersionControl.Client
Microsoft.WorkItemTracking.Client
I include these references in the class library called, say, Utility. I then proceed to wrap objects in those assemblies in helper objects. There are no errors, intellisense works correctly, and so forth.
When I want to use that class library in another project inside the same solution, say, TestCLI, I add a reference to the Utility project by selecting the project from the solution references tab. I can then use the Utility classes without issue, until I go to build.
When I build the solution, it throws an error such as:
The type 'Microsoft.TeamFoundation.VersionControl.Client.BranchObject' is defined in an assembly that is not referenced. You must add a reference to assembly 'Microsoft.TeamFoundation.VersionControl.Client, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
In the past, I have worked around this issue by adding the same references to the calling project (TestCLI) in addition to the class library (Utility). I feel that this is defeating one of the purposes of having a class library and that I've missed a step in order to not have to worry about library references in my calling project.
Is there some way to resolve these dependencies without including the references in both the class library and the calling project? Am I structuring my solutions incorrectly? Am I thinking about class libraries in the incorrect manner?
The references are required because you are exposing objects from the other libraries, and then to use these classes the final program needs the references.
To avoid this you must hide the external objects, through a wrapper, a copy of the class or anything else, it depends primarily on what and why you are exposing those objects.
I'm developing a WCF service that uses an interface (not the ServiceContract interface) to perform some internal work. My goal is to extend the functionality of this service after deployment by delivering New DLLs with classes that implement this interface (and corresponding web.config updates).
I'm starting with just one class that implements the interface. In my solution, I have the Service in one project (WCF Service Application) with the interface definition, and the class that implements the interface in another project (Windows Class Library).
I am using the following code to dynamically load the class (based on a parameter passed when the service is called):
InterfaceFoo af = (InterfaceFoo)System.Activator.CreateInstance(AssemblyQualifiedName, ClassType).Unwrap();
When this line is called, I get a FileNotFoundException, Could not load file or assembly.
I believe the above code is correct, as I have it working at runtime from a separate proof of concept project once it's built and deployed, and the DLL is placed in the same folder as the EXE. I believe my problem is related to how I've referenced the projects, or the variables I'm passing to the CreateInstance() method when run within Visual Studio.
What I've tried and I still get the same error: In the WCF Service Project I've set the Class Library project as a reference. In the WCF Service Project I've added a link to the interface implementing class.
I'm wondering if the values I'm using for AssemblyQualifiedName and ClassType won't work within Visual Studio since they aren't yet deployed?
Any advice is appreciated, even if you think a completely different approach is better.
ADDED AFTER INITIAL POST:
I had an idea after posting, I moved the interface implementing class from the Class Library Project to the WCF Service Project. When I do this, it works. That to me eliminates the assembly and type parameters as issues, and the issue is that I'm not linking correctly to the Class Library Project.
You can move your interface defenition to another shared library (dll) and then use it.
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
so I implemented a really simple plugin system.
i have the following Assemblies:
MainApp
IPlugin
PluginApp
Both MainApp and PluginApp conatin a reference to the IPlugin. Now, in MainApp I scan a plugins folder and search for things that implement the IPlugin interface.
However, it is not working because both MainApp and PluginApp reference their own copy of IPlugin.dll so they are not recognized as a match when using Type.IsAssignableFrom()!
help?
You could try putting your code that defines the plugin into a satellite dll assembly. That way both your main code and the plugins reference the same types.
If the plugin can maintain it's own dll instead of using the same dll as the application you will run into versioning issues. How will your main app handle calling plugins that don't implement the same interface?
When we did this in our own software we had to resort to reflection method calls instead of casting to the interface. It wasn't elegant.
What about adding the assemblies dll into the plugin directory. They have to reference the dll when they create their application, but force them to use the main assemblies version of the dll when the plugin is actually run?