Prevent dependencies being required by other projects - c#

I am writing a project which will encapsulate multiple Calendar APIs (Google Calendar, Outlook ect) in one service. This will allow me to integrate different APIs which can be mapped to our domain model. However I am having issues with required dependencies spilling over into other projects. Here's an example:
I have created a generic class which does most of the work and conversions from the API model to our model. Here's an example:
public abstract class CalendarAPIBase<TEventType> : ICalendarAPI
{
public CalendarEvent Get(string id)
{
if (string.IsNullOrEmpty(id))
throw new ArgumentNullException("id");
return Convert(GetEvent(id));
}
public List<CalendarEvent> GetAll()
{
List<CalendarEvent> result = new List<CalendarEvent>();
List<TEventType> es = GetAllEvents();
foreach (TEventType e in es)
result.Add(Convert(e));
return result;
}
protected abstract List<TEventType> GetAllEvents();
protected abstract CalendarEvent Convert(TEventType obj);
//More stuff below.
}
So this is a beautiful thing, anything that inherits CalendarAPIBase doesn't have to do much work other than getting the data from the API, the base class will handle the conversions.
Ok, so here's where things go wrong. I have created a GoogleCalendarAPI class, which inherits from CalendarAPIBase. It passes in the Event class, which belongs to a NuGet package Google.Apis.Calendar.v3.
public class GoogleCalendarAPI : CalendarAPIBase<Event>
The problem here is that this class is exposing the Event class, therefore anything that references this project will also need to reference Google.Apis.Calendar.v3. Ideally anyone wishing to use this service will only have to reference just the project and not have to worry about installing other NuGet packages.
How can I restructure my classes to prevent this from happening?

The most straightforward way to resolve this stuff is an Abstract factory pattern.
First, you make CalendarAPIBase<TEventType> and all its descendants internal. All the public stuff has to be concentrated within a public ICalendarAPI interface.
Next step is introducing public classes like this:
public static class GoogleCalendarAPIFactory
{
public static ICalendarAPI Instantiate( ....... )
{
.......
return new GoogleCalendarAPI( ..... );
}
}
The factory will make all the TEventType hassle hidden ftom the library user, therefore he will not need to add all the packages containing TEventType implementations.

I'm not sure if you can avoid referencing 3rd party assemblies if you use classes like Google.Apis.Calendar.v3.Event directly in your code.
However, you can use ILMerge to merge 3rd party API into your own, that way the dependencies of your assemblies will be deployed along with your assemblies.
I usually use ILMerge in the post build event.
For example:
After GoogleCalendarAPI project is built, merge GoogleCalendarAPI.dll and Google.Apis.Calendar.v3.dll and save it in "GoogleCalendarAPI_location\mergerd\GoogleCalendarAPI.dll"
Copy "GoogleCalendarAPI_location\mergerd\GoogleCalendarAPI.dll" to the location of the original GoogleCalendarAPI.dll and replace it.
Now you've got GoogleCalendarAPI.dll with Google.Apis.Calendar.v3 baked into it.
Now every assembly that references GoogleCalendarAPI.dll gets both.

Related

How to connect two classes together

I am making a gallery tool that lets you browse and edit objects. I have a 'Library' class that manages the fetching and displaying of the gallery list. I also have an 'ActiveItem' asset that loads all the information of the selected object and deals with modifying it.
Now, there's some information that is stored in the 'library' class (for example the filepath) that I want to use in my activeitem.
I'm a bit confused as to how I can set this up efficiently.
I thought about embedding the activeitem class in the library class, but it gets a bit annoying to have to access all functions and properties of the activeitem through the library class (so instead of writing activeitem.Load() I would have to write lib.activeitem.Load() ). Activeitem already goes 4 levels deep and it's getting a bit much.
Are there other ways of setting this up? Can I store a reference of the library class instance inside the activeitem class, so that the activeitem class can fetch a property of the library instance?
Edit: added some code snippets
This are the class definitions:
class Library
{
...
public string LibDirectory;
...
}
class ActiveAsset
{
...
public SaveAsset()
{
//this method needs to know the LibDirectory property of the libraryclass
}
}
On initiating my winform, I initiate both classes:
Library lib = new Library();
ActiveAsset activeAsset = new ActiveAsset();
Given the concerns in the question comments, if you want ActiveAsset to be able to read information from Library you could change ActiveAsset's constructor to take in Library and store it internally as a private var.
class ActiveAsset
{
private Library _lib
public ActiveAsset(Library lib) {
this._lib = lib
}
public SaveAsset()
{
// reach lib instance from here
this._lib.LibDirectory
//this method needs to know the LibDirectory property of the libraryclass
}
}
If you are worried about design and coupling you could make in interface for Library and then make the constructor use that instead of the Library class
interface ILibrary {
string LibDir { get; set; }
}
class Library : ILibrary {
}
class ActiveAsset
{
private ILibrary _lib
public ActiveAsset(Library lib) {
this._lib = lib
}
public SaveAsset()
{
// reach lib instance from here
this._lib.LibDirectory
//this method needs to know the LibDirectory property of the libraryclass
}
}
As for performance and creating deep levels of nested classes I don't think you will have to worry so much about it, chances are you will hit data save/retrieve performance issues before anything like too many classes. That kind of performance design is only really important when you try to make you code work on small platforms where memory is limited like rasberryPi and such.
I would suggest creating a wrapper class which holds both the Library and the ActiveItem instances. Thus you can have more generalised methods like:
GetAllItems() - gets all items from the library
ActivateItem(Item item) - activates the item provided (stores the given item to a variable in the wrapper class)
etc. Think of that wrapper class as the manager of your application. You would only like to work with that manager regardless of what's beneath it.

Allow subclass instantiation only on the assembly of the superclass in C#

Imagine the following scenario in a Xamarin solution:
Assembly A (PCL):
public abstract class MyBaseClass
{
public MyBaseClass()
{
[...]
}
[...]
}
Assembly B (3rd Party Library):
public class SomeLibClass
{
[...]
public void MethodThatCreatesClass(Type classType){
[...]
//I want to allow this to work
var obj = Activator.CreateInstance(classType);
[...]
}
[...]
}
Assembly C (Main project):
public class ClassImplA:MyBaseClass{
[...]
}
public class ClassImplA:MyBaseClass{
[...]
}
public class TheProblem{
public void AnExample(){
[...]
//I want to block these instantiations for this Assembly and any other with subclasses of MyBaseClass
var obj1 = new ClassImplA()
var obj2 = new ClassImplB()
[...]
}
}
How can I prevent the subclasses from being instantiated on their own assembly and allow them only on the super class and the 3rd Party Library (using Activator.CreateInstance)?
Attempt 1
I though I could make the base class with an internal constructor but then, I saw how silly that was because the subclasses wouldn't be able to inherit the constructor and so they wouldn't be able to inherit from the superclass.
Attempt 2
I tried using Assembly.GetCallingAssembly on the base class, but that is not available on PCL projects. The solution I found was to call it through reflection but it also didn't work since the result of that on the base class would be the Assembly C for both cases (and I think that's because who calls the constructor of MyBaseClass is indeed the default constructors of ClassImplA and ClassImplB for both cases).
Any other idea of how to do this? Or am I missing something here?
Update
The idea is to have the the PCL assembly abstract the main project (and some other projects) from offline synchronization.
Given that, my PCL uses its own DB for caching and what I want is to provide only a single instance for each record of the DB (so that when a property changes, all assigned variables will have that value and I can ensure that since no one on the main project will be able to create those classes and they will be provided to the variables by a manager class which will handle the single instantions).
Since I'm using SQLite-net for that and since it requires each instance to have an empty constructor, I need a way to only allow the SQLite and the PCL assemblies to create those subclasses declared on the main project(s) assembly(ies)
Update 2
I have no problem if the solution to this can be bypassed with Reflection because my main focus is to prevent people of doing new ClassImplA on the main project by simple mistake. However if possible I would like to have that so that stuff like JsonConvert.DeserializeObject<ClassImplA> would in fact fail with an exception.
I may be wrong but none of the access modifiers will allow you to express such constraints - they restrict what other entities can see, but once they see it, they can use it.
You may try to use StackTrace class inside the base class's constructor to check who is calling it:
public class Base
{
public Base()
{
Console.WriteLine(
new StackTrace()
.GetFrame(1)
.GetMethod()
.DeclaringType
.Assembly
.FullName);
}
}
public class Derived : Base
{
public Derived() { }
}
With a bit of special cases handling it will probably work with Activator class , but isn't the best solution for obvious reasons (reflection, error-prone string/assembly handling).
Or you may use some dependency that is required to do anything of substance, and that dependency can only be provided by your main assembly:
public interface ICritical
{
// Required to do any real job
IntPtr CriticalHandle { get; }
}
public class Base
{
public Base(ICritical critical)
{
if (!(critical is MyOnlyTrueImplementation))
throw ...
}
}
public class Derived : Base
{
// They can't have a constructor without ICritical and you can check that you are getting you own ICritical implementation.
public Derived(ICritical critical) : base(critical)
{ }
}
Well, other assemblies may provide their implementations of ICritical, but yours is the only one that will do any good.
Don't try to prevent entity creation - make it impossible to use entities created in improper way.
Assuming that you can control all classes that produce and consume such entities, you can make sure that only properly created entities can be used.
It can be a primitive entity tracking mechanism, or even some dynamic proxy wrapping
public class Context : IDisposable
{
private HashSet<Object> _entities;
public TEntity Create<TEntity>()
{
var entity = ThirdPartyLib.Create(typeof(TEntity));
_entities.Add(entity);
return entity;
}
public void Save<TEntity>(TEntity entity)
{
if (!_entities.Contains(entity))
throw new InvalidOperationException();
...;
}
}
It won't help to prevent all errors, but any attempt to persist "illegal" entities will blow up in the face, clearly indicating that one is doing something wrong.
Just document it as a system particularity and leave it as it is.
One can't always create a non-leaky abstraction (actually one basically never can). And in this case it seems that solving this problem is either nontrivial, or bad for performance, or both at the same time.
So instead of brooding on those issues, we can just document that all entities should be created through the special classes. Directly instantiated objects are not guaranteed to work correctly with the rest of the system.
It may look bad, but take, for example, Entity Framework with its gotchas in Lazy-Loading, proxy objects, detached entities and so on. And that is a well-known mature library.
I don't argue that you shouldn't try something better, but that is still an option you can always resort to.

How can I get a class instance from a plugin?

I have built a plugin system, where I can dynamically load classes into my application (IModule is an interface, so I know the plugin will behave correctly):
var dll = Assembly.LoadFile("path/to/a/dll");
foreach (Type t in dll.GetExportedTypes()) {
if (typeof(IModule).IsAssignableFrom(t)) {
IModule mod = (IModule)Activator.CreateInstance(t);
}
}
So, from my "main" application, I can get and instantiate classes in my plugin. What I would like now, is to be able to get to the classes of the "main" application, from the plugin.
I tried using Type.GetType("NameOfClass"), but that returns null.
This is bound to turn ugly if you need to do it without altering the main module at all, which turns out to be the case. So the following suggestion is a kludge, but I think a kludge may be the best you can hope for in this case.
The static method Assembly.GetCallingAssembly() will return the assembly that called the method you're currently in, so one thing you could do is find a place where the main module directly calls some method M of the plugin modules. Fingers crossed, maybe there's some kind of initializer method that gets called early on.
In M, call Assembly.GetCallingAssembly() and stuff the result in some static field that you can use later to create instances of classes that are defined in the main module.
I think you misunderstood plugin-like concept. You should implement API library which purpose will be to store public plugin interfaces. Those interfaces you will be using in your plugins, and just instantiate your classes through some IoC framework. For example, you can use Ninject:
public class MyPlugin : IModule
{
public MyPlugin(MainApp.API.IMainAppInterface instance)
{
//do something with it.
}
}
public class MyPluginModule: NinjectModule
{
protected override void Load(IKernel kernel)
{
kernel.Bind<MyPlugin>().To<IModule>();
}
}
And in your main application you just load those modules from some folder.

How to prevent constructor misuse in c# class

I've been trying to implement a loosely coupled application in an asp.net MVC5 app. I have a controller:
public class HeaderController : Controller
{
private IMenuService _menuService;
public HeaderController(IMenuService menuService)
{
this._menuService = menuService;
}
//
// GET: /Header/
public ActionResult Index()
{
return View();
}
public ActionResult GetMenu()
{
MenuItem menu = this._menuService.GetMenu();
return View("Menu", menu);
}
}
And service being used in this controller is:
public class MenuService : IMenuService
{
private IMenuRespository _menuRepository;
public MenuService(IMenuRespository menuRepository)
{
this._menuRepository = menuRepository;
}
public MenuItem GetMenu()
{
return this._menuRepository.GetMenu();
}
}
And the repository being used in the service class is:
public class MenuRepository : IMenuRespository
{
public MenuItem GetMenu()
{
//return the menu items
}
}
The interfaces used for the service and repository are as such:
public interface IMenuService
{
MenuItem GetMenu();
}
public interface IMenuRespository
{
MenuItem GetMenu();
}
The constructor for HeaderController takes in the MenuService using Constructor Injection, and I have ninject as the DI container handling this.
It all works great - except, in my controller, I can still do this:
MenuItem menu = new MenuService(new MenuRepository());
...which breaks the architecture. How can I prevent the 'new' being used in this way?
One way to do it would be to move your interfaces and implementations into separate Visual Studio projects / assemblies and only reference the implementation project in the project(s) that actually needs it - everything else can reference the interface project for your IMenuService - at that point the code can consume the interface, but not actually new up any implementations itself.
You can then reference the implementation project wherever you DI in your dependencies.
WebApp Solution:
WebApp Proj (Controllers etc.) --> Service Interface Proj
Service Impl Project --> Service Interface Proj
Even so this is a good approach, it's not fool proof by all means - the other component is education and code review to come up with best practices that work for your team such as testability and dependency injection.
I assume part of the issues with manually instantiating the object may come with working with a large team, whereby some members are using the constructor injection technique the wrong way. If that is the case, I found pretty much by educating them on the framework resolved most of the issues. Occasionally, you would find someone doing it the wrong way, but not often. Another alternative could be to add an [EditorBrowsable(EditorBrowsableState.Never)] attribute on the controller constructor. The constructor will disappear from intellisense; well, it will appear to be gone. It can still be used, however.
You could break out the implementations into another DLL not directly references (implicitly referenced) by the MVC project, and thus since there isn't a direct reference, you can't use those types directly. With the interfaces in one project, which each project references, and the project with the implementations indirectly referenced, only the interfaces would thus be included. I'd recommend including a direct reference in the unit test project, if you are doing unit tests, to enhance test coverage.
Couple of potential options (which I've never tried, but might have some legs):
you could maybe write an FXCop rule which errors if the constructor is used in the code.
you could mark the constructor as obsolete, and have the build server fail if you use obsolete methods in the code.
If the DI container uses it through reflection this should all be ok (although in the FXCop case you could probably not throw if it was in a method in the NInject namespace)
As general design principle, interfaces (Contracts) should be in one assembly and the implementation should in another assembly. The Contracts assembly should be reference in MVC project and implemented assembly should be copied in "bin" folder. Than use "Dynamic Module Loading" to load types. In this way you will avoid the above mentioned problem and this is more extensive solution. Because you can replace implementation without building UI and Contact Assemblies.

Implement partial methods across multiple assemblies

In one of the applications I am working on, there are two basic functionalities included: Create and Update.
However, there is a need sometimes to add custom code, so I thought of extending the code by allowing 3rd parties to write and embed their own code:
OnCreating
OnCreated
OnUpdating
OnUpdated
Is there a way to enable the above across multiple assemblies? MEF might help here?
Thank you
Regards
Thanks all for your replies.
Having such an interface means each external assembly has to implement that interface as needed. Then, my application's code, needs to loop through the currently running assemblies, detect all classes implementing that interface, and run their methods?
Does MEF fit here? I can export the implementation from external assemblies and import them inside my app?
Thank you
Regards
You can't have partical classes accross assemblies because partial classes are a language feature, and not a CLR feature. The C# compiler merges all the partial classes into one real class, and that single class the the only thing left after compilation.
You have a couple of alternatives:
Offer events
Make the methods virtual and override them
Use an interface
Your problem looks like it fits events best. The user can simply subscribe to them in the other assembly.
Regarding your MEF question, you could probably do something like the following to run methods from an interface:
var catalog = new DirectoryCatalog("bin");
var container = new CompositionContainer(catalog);
container.ComposeParts();
var plugins = container.GetExportedValues<IPlugin>();
foreach (IPlugin plugin in plugins)
{
plugin.OnCreating();
}
Or create an interface with events as Brian Mains suggested:
public interface IPlugin
{
event OnCreatingEventHandler OnCreating;
}
then the above code would be more like:
var catalog = new DirectoryCatalog("bin");
var container = new CompositionContainer(catalog);
container.ComposeParts();
var plugins = container.GetExportedValues<IPlugin>();
foreach (IPlugin plugin in plugins)
{
plugin.OnCreating += MyOnCreatingHandler;
}
I think I like the latter for the method names you specified. For my plugin work, I've created an interface similar to the following:
public interface IPlugin
{
void Setup();
void RegisterEntities();
void SeedFactoryData();
}
The RegisterEntities() method extends the database schema at runtime, and the SeedFactoryData() method adds any default data (eg. adding default user, pre-population of Cities table, etc.).
Having partial classes supported across assemblies isn't supported.
The reason being that all partial class definitions are combined into a single class during compile time. That single class resides in a single assembly.
Consider using an interface:
IUpdatableObject<X>
Creating(X obj);
Created(X obj);
Updating(X obj);
Updated(X obj);
And then use this interface to add in custom code; each third party can implement this interface (well either they or you can through a wrapper) and this can be a tie into adding custom business logic.
HTH.
You (or the user) can use extension methods:
http://msdn.microsoft.com/en-us/library/bb383977.aspx
Partial methods and classes must be in the same assembly. Partial methods are compiled out if not used. If you need extension points for you classes you should look into virtual methods or events.
Partial classes across assemblies aren't supported because the concept behind the partial class is to allow multiple developers to contribute different methods and members for the same class under a particular namespace.
This was done in order to help developers to sync the code into a single class, inside one assembly, build after compilation.

Categories