I’m a C++ guy which has to work with some C# projects hence I have question. Having two projects placed on different svn servers I need them to share interface classes. How it should be solved in C#.
For example I have cs file which have interface and class used to pass data to the interface i.e.
Public Class data
{
public int a;
public int b;
}
Public Interface Ifoo
{
int foo(data);
}
This interface is implemented in ProjectA and used by ProjectB.
I want to be able to chose implementation of the interface so that in tests of ProjectB I will use special implementation of Ifoo interface.Chosing different dll using :
Assembly assembly = Assembly.LoadFrom(asm_name);
fooer = assembly.CreateInstance(class_name) as Ifoo;
Where I should place Ifoo interface?
I thought it should be placed in ProjectA svn repo (as ProjectA is owner of the interface) and then checkout it as an external with checkout of ProjectB .
Can you tell me what is the rule of thumb in such case?
BR
Krzysztof
First of all, whatever you decide to put your interface and asspciated data class (project A or project B svn or a new one), the first (and quite ovious) recomendation is that you put them together on its own library (DLL), without any dependency on other objects, so that becomes easy to share it across different projects.
To use it on a different project (do not matter if on another svn repository or not), you will have to give to that project physical access to this interface/data class. Being on its own dll and without the constraint of requiring other objects, it's a simple matter of add a reference of the library in the project.
With local copies of both projects, you don't need to copy the library itself into the other project.
In any case, you have to think well of your interface and data, so that you do not contantly make changes to them, in order to avoid having problems of compatibility between the projects. If you need to "add" something to the interface because of new features, create a new interface instead (and put it on other DLL). This way you will maintain compatibility with other projects that do not implement the new features.
If the data associated with the interface is so specific that any class implementing this interface will be used ONLY BY project A, so, the obvious place to put the DLL is into the project A. Usually this is the case when a software has the aability to use plugins. The interfaces are in a dll that can be "public" provided to plugin developers that do not have access to the main project itself. This is so simple as to make the DLL available to download. Beijng the SAME dll used on both main project and plugins, there will be no problems (than the reason to not change it).
But if your interface is more "generic" and is used to create something like a framework, where different projects (not related/not dependent) can use it alone, than, the suggestion to separete it in a third project (with its own svn) is more interesting. Using good polices regarding the development of this interface, will be less problematic to mantain the framework.
In the comments you said you can relate the "interface" to the project A, but if you can use it in project B without project A being involved, you can relate the interface to project B as well, and so, the option of moving the interface/associated data to a separetely project is preferable.
In any case, the underline implementation is irrelevant, as the main reason why we use interfaces in C# is exactly to be able to use an object in a "generic way" whithout (necessarily) having to care about how it is implemented.
Related
I have two versions A and B of the WinIDEA library. and they have the same name i.e. IConnectCSLib. There are some functions in these two versions which are similar, but some functions which are different.
So far, I had implemented a static wrapper of the version A called WinIdeaWrapper to write functions, because that is all I needed to get it to do what I wanted. And implementing it as static made sense because the wrapper was supposed to be stateless, and WinIDEA always changes state without any notification to the wrapper. This wrapper was being used in different visual studio solutions to run WinIDEA and get stuff done.
Lets assume that the Visual Studio solution that was working up until now in production was called BMW.sln. In addition I have another solution called Refactor.sln which includes all the projects in my repo, which I use to refactor stuff, because there are many solutions in our repo, and refactoring in only one creates many errors in other solutions.
Now I have to support a project that only works with version B of WinIDEA. The dll provided with the version B has a 50% overlap with the version A in terms of functionality. So 50% of the functions from WinIdeaWrapper will work with version B, which other 50% will fail. So, obviously, given the project organization structure of the Visual Studio, I have to separate the dlls and their wrappers. Lets assume, all the APIs are organized for this new project in hyundai.sln
How can I implement a wrapping classes structure (preferably static (or singleton at worst)) so, that I can avoid code replication for the common functionality between version A and B. At the same time, I can have function which can be overridden from both wrappers A and B with different internal workings. which can be referenced by different solutions, but at the same time can be included in one super solution refactor.sln for easy refactoring.
So far, I have created two different VS projects called Winidea_A and Winidea_B, which will house their respective WinIdea dlls and wrappers. But, I am not sure how to link these classes to a common class so that I dont have to implement same function in two places.
My colleague suggests using two different interfaces called IWinideaGeneric, and IWinideaSpecific, and implementing them in the wrappers. I can see how that would work but I cannot imagine how the namespace, or class name conflict will work in the refactor solution.
I have a large collection of custom C# classes that roughly follow the MVC pattern that I reuse over and over to build GUI and command line PC applications with different groupings of functionality. For example there are classes for importing and exporting files, classes for manipulating data, classes for monitoring, utility classes, etc.
These classes are currently grouped into a set of assemblies. The higher-level assemblies reference lower-level assemblies, which in turn reference even lower-level assemblies.
All the classes are marked as public so when I build a PC application I can reference the appropriate assemblies and uses the classes in a modular fashion.
When I release a PC application I use a .NET obfuscator to merge the assemblies and the EXE into a single EXE so end users cannot see the APIs of all the classes and assemblies.
Now I would like to create a .NET assembly from my collection of classes that only exposes a specific, limited API and give it to end-users. I guess this is the facade design pattern.
For example I would like to take assemblies A and B and use classes from those, say A.Foo, A.Bar, A.Baz, B.Foobar, B.Bazbar, B.Bazfoo and create a new assembly, C, that has a single public class C.MyClass. Assembly C references assemblies A and B. End users can only see C.MyClass and they can't see or access A.xxx or B.xxx.
Is there a clean way of doing this that doesn't require drastic changes to my current collection of classes and assemblies (as they are already used in multiple other projects)?
Or is this something that is typically handed in the merging/obfuscation stage instead?
Thanks!
I'm developing an application that heavily relies on a plugin architecture (*).
However I'm not sure what design pattern to use for dependencies between plugins, e.g. when plugin A depends on plugin B, possibly with some constraints (plugin B version between v1.05 and v1.30 or so)
My thoughts so far:
I could specify an interface for plugin B that never changes, and have plugin A reference this interface project only. Plugin B is then free to implement this in whatever way with versioning, and the latest available implementation will just be dependency-injected into the requested interfaces.
This could work, but it seems as though defining an interface which is very much tailored to the specific plugin's functions is a bit unnecessary; plus I suppose that I'd have to stick to that interface then; I could only enhance the plugins implementation in future versions easily, but not the interface.
I could ignore interfaces and just develop the plugins' implentations. Plugin A's project could then directly reference Plugin B's .dll. But as far as I know, this would cause errors when replacing Plugin B's .dll with a newer version, unless I add explicit version redirects in my applications config, wouldn't it?!
Are there any best practices? I suppose this issue is very similar to Nuget packages' depdendencies - does anyone happen to know how they have solved it?
Thanks
(*) in case it matters, my plugin architecture works as follows: I have all my plugins implement an interface IPlugin.
My main app then scans the plugin directory for all .dlls, filters out all classes that implement IPlugin, and uses Ninject to add a binding from IPlugin to the specific implementation (in the end, there'll be several bindings available for IPlugin, e.g. IPlugin -> Plugin1, IPlugin -> Plugin2 etc.). I'm then using Ninject to request/create a singleton instance of each plugin and register it in my main app. That way, my plugins can "request" dependencies via constructor arguments and Ninject/DI takes care of providing those.
As far as I am aware, Nuget tracks library dependencies using the metadata stored in the nuget package file. If I were you I'd avoid implementing arbitrary restrictions. What if one of your plugin developers wants to create a shared support library of useful classes, for example?
To my mind, a plugin should be a black box of functionality. If a plugin needs another plugin, then they should communicate via a standardized messaging platform rather than directly.
That said, you could always scrape all interface implementations from the library you load and hook those up as well as your plugins. That way the plugin developer can "request" implementations of those interfaces as well as plugins.
You'll need to cope with massive class libraries (I recommend only hooking up in Ninject interfaces that are referenced in plugin constructors) and with potential conflicts (two plugins might expect separate implementations of the same interface - which is the main reason I believe that a plugin should take care of itself internally, rather than hoping its design time expectations are fulfilled by the external plugin manager).
And in answer to (2), as long as the methods and properties you reference don't change name or signature, you shouldn't have any problems using a newer version of DLL B with DLL A. If you change a return type, change from a public field (which shouldn't exist in the first place) to a public property, change the parameters on a method or anything of that nature on a class that you're using from DLL B in DLL A, a recompile of A would be required.
I'm creating a project in which I made my own classes but now I need to support plugins. So I need an interface to then export as dll, so people can create plugins using that dll as the interface.
Now I'd like the plugin that is being created to be able to use my custom types.
For example:
My project has a class named Product.
I then created an interface with the following method:
Product[] getProducts();
Then a user that creates a plugin overrides that method and needs to have access to the Product class.
How am I going to do this?
I've tried to compile my whole project as a .dll but that just gives alot of errors.
I've also tried to compile the neccesary project files to a .dll but my project refers to almost every part so it still has errors.
I'd like to google it, but I've no idea what to google on.
Thanks.
Edit:
I'm using Visual C# 2013 express edition.
Create a separate project that only contains interfaces. Your main product would reference this assembly and the extensions would also reference this assembly.
For example, lets say you want extensions to provide a method GetAnimals() which returns an IEnumerable. Your second project would contain an interface that looks like this:
public interface IAnimal
{
UInt32 Height { get; }
}
public interface IExtension
{
IEnumerable<IAnimal> GetAnimals();
}
The project would be of type class library and would only contain these interfaces. The project would not reference your main project. Your main project would reference this class library and you could give the class library to your users/customers/extenders and they could build extensions by implementing IExtension.
Update: A key in making extensions is that your users will never have direct access to any of your concrete types. They will always only have access to the interfaces that your concrete types implement. You will need to structure your application to have interface hierarchies for everything so that you can provide those interfaces to the user. You want to avoid putting any concrete types into your extension class library.
I have a solution with 2 projects.
One, Raven, is a simple base that provides data for the second project, PPather, to do stuff with. The second project depends on the first to compile so to build it, I add a reference to Raven. All works well so far.
Now I want Raven to launch PPather. But it can't see the PPather naemspace so I can't. All efforts to resolve this lead to circular reference errors.
Anyone know how I can get Raven to see the namespace of the PPather project that depends on it?
You can't - there is no way to reference assemblies in a circular manner like you want to do. Most likely you have not properly designed these assemblies if you need to create a circular reference.
Your first assembly is a dependency so there should not be any code in there that knows about anything other than its dependencies. Once your assemblies become "smart" and begin to have knowledge of anything outside their own dependencies you will begin to have serious maintenance and scalability headaches. I would look into reorganizing your code in such a manner that you do not need to create the circular reference.
As Andrew says, you can't and it doesn't make much sense that you'd want to.
Basically, do one of the following:
Merge the assemblies; if they really inter-depend tightly, then they really should not be separate in the first place.
Re-design the assemblies so that they do not directly depend on each other in both directions; for instance, make assembly A depend on an interface defined in assembly C, and have assembly B implement this interface (both depend on C).
There is a ton of stuff you can do to achieve this if you are not willing to combine them into one component. All basically strive to either invert one of the dependencies or to create a third component on which both depend.
It seems that Raven is the starting point, so one possible solution is to create a base class or interface in the PPather component which reflects the feature set that PPather seeks in Raven. Raven can then implement this base class and then include a "this"-pointer when instantiating/invoking PPather. PPather will expect a pointer to the base class (or interface) in his own assembly, and therefore will never "know of" Raven except through his own abstraction. Therefore, the circular dependency will be broken (by means of dependency injection).
It is fortunate that you can not add circular references - because they cause maintenance nightmares.
You want Raven to launch PPather? Is PPather as console/windows application? Use Process.Start to do that (and store the location of PPather in the registry somewhere).
Alternatively create interfaces for the classes that you need out of PPather - and make the classes in PPather implement those interfaces.
interface IPPatherInterface // Inside of Raven.
{
void Foo();
}
class PPatherClass : IPPatherInterface // Inside of PPather
{
// ...
}
class SomeRavenClass // Static maybe? Inside of Raven
{
void SupplyPPatherClass(IPPatherInterface item) { ... }
}
You now have a way for PPather to supply that interface's implementation to Raven.
Branch out the calsses in raven that Panther needs to use from raven to a different assembly, and have both panther and Raven reference them.
Although to be honest if Raven needs to run panther then i think your design is a bit Off. you should break off your code into something more manageable.