Reputation: 937
I have three assemblies, A.dll
, B.dll
, C.dll
that all define a single namespace A, B, C and a single class A, B, C.
The classes in each assembly have the exact same API, identical in every way.
I now need to write an application that uses all three assemblies and I am struggling to find the best way to do this.
For example the classes define the following function:
string GetName();
In my application I have a matching function, but how can I simplify the implementation?
A MyA = new A();
B MyB = null;
C MyC = null;
public string GetName() {
if (MyA != null) return MyA.GetName();
else if (MyB != null) return MyB.GetName();
else if (MyC != null) return MyC.GetName();
}
I have a lot of functions in this API so it would be messy to do this if/else over and over again.
I thought about defining an interface for the API, but I don't want to add another assembly that my application and these three assemblies are dependent on. I also don't want to create an inter-dependency between any of these assemblies. This is because the assemblies are used individually in other situations that unfortunately only allow for a single assembly, which is out of my control.
I thought about using reflection and delegates:
private void GetAPI() {
var Api = MyA;
Type t = Api.GetType();
System.Reflection.MethodInfo m = t.GetMethod("GetName");
_GetName = (GetNameDelegate)Delegate.CreateDelegate(typeof(GetNameDelegate), Api, m);
}
public string GetName() {
return _GetName();
}
This works, but how do I expand this to re-use this piece of code for all three assemblies? I.e. how to pass in MyA, MyB, MyC into the GetAPI function?
Thanks!
Upvotes: 0
Views: 210
Reputation: 684
Assuming you can't go about this using standard OOP patterns (interface, inheritance), you could make some helper methods to avoid writing lots of code to invoke your delegates. For example, these methods below allow you to do expressions like this on your Api classes:
var nameForApiA = Wrapper.Invoke<ApiA, string>(apiA => apiA.GetName());
Note that this calls Activator.CreateInstance
on the type parameter, so if your API classes have constructor parameters, those will need to be handled another way.
public class Wrapper
{
public static void Invoke<TApi>(Action<TApi> method)
{
var instance = Activator.CreateInstance<TApi>();
method.Invoke(instance);
}
public static TReturn Invoke<TApi, TReturn> (Expression<Func<TApi, TReturn>> method)
{
var instance = Activator.CreateInstance<TApi>();
Func<TApi, TReturn> compiled = method.Compile();
return compiled(instance);
}
}
Upvotes: 1
Reputation: 513
I suggest to create an Interface. And use the interface instead of the actual class. Another way is to create and an Abstact Class and ovverrid all the function for each class of yours
Upvotes: 1