Reputation: 9713
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?
Upvotes: 0
Views: 67
Reputation: 483
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.
Upvotes: 0
Reputation: 4253
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.
Upvotes: 1