I do not control the general interface for two third-party classes. External polymorphism?

I need a small drawing direction here. New in C #.

I work with a third-party developer kit that wraps a web service. There are two specific classes that I'm dealing with relatively similar that are in two different namespaces in devkit and there is no common base class. I would like the program against a common interface for both of them. I accidentally put together an implementation that essentially wraps the wrapper, but I am sure that this is not the most efficient method due to the ongoing casting.

I have been digging articles about adapters, interfaces, extension methods, etc., but I don't have much time, so if I could get a push in one direction, that would be very useful.

using ThirdParty.TypeA.Employee; using ThirdParty.TypeB.Employee; public class Employee { private object genericEmployee; private EmployeeType empType; public enum EmployeeType { TypeA = 0; TypeB = 1; } public Employee(Object employee, EmployeeType type) { genericEmployee = employee; empType = type; } public String Name { if (empType == EmployeeType.TypeA) return (ThirdParty.TypeA.Employee)genericEmployee.Name; else return (ThirdParty.TypeB.Employee)genericEmployee.Name; } public String Age { if (empType == EmployeeType.TypeA) return (ThirdParty.TypeA.Employee)genericEmployee.Age; else return (ThirdParty.TypeB.Employee)genericEmployee.Age; } } 

Rev 2:

 class EmployeeTypeAAdapter : TypeA, IEmployeeAdapter { TypeA _employee; public EmployeeTypeAAdapter(TypeA employee) { _employee = employee } public String Name { get { return _employee.Name; } set { _employee.Name = value; } } public String Balance { get { if (_employee.Balance != null) { decimal c = _employee.Balance.Amount; return String.Format("{0:C}", c); } else { return ""; } } } //... } class EmployeeTypeBAdapter : TypeB, IEmployeeAdapter { TypeB _employee; public EmployeeTypeAAdapter(TypeB employee) { _employee = employee } public String Name { get { return _employee.Name; } set { _employee.Name = value; } } public String Balance { get { if (_employee.Balance != null) { decimal c = _employee.Balance.Amount; return String.Format("{0:C}", c); } else { return ""; } } } //.... } 
+6
source share
2 answers

Try this approach:

 public interface IEmployeeAdapter { string Age { get; set; } string Name { get; set; } } class EmployeeTypeAAdapter : TypeA, IEmployeeAdapter { public EmployeeTypeAAdapter(TypeA employee) { } } class EmployeeTypeBAdapter : TypeB, IEmployeeAdapter { public EmployeeTypeBAdapter(TypeB employee) { } } public static class EmployeeAdapterFactory { public static IEmployeeAdapter CreateAdapter(object employee, EmployeeType type) { switch (type) { case EmployeeType.TypeA: return new EmployeeTypeAAdapter((TypeA)employee); case EmployeeType.TypeB: return new EmployeeTypeBAdapter((TypeB)employee); } } // or without enum public static IEmployeeAdapter CreateAdapter(object employee) { if (employee is TypeA) return new EmployeeTypeAAdapter((TypeA)employee); if (employee is TypeB) return new EmployeeTypeABdapter((TypeB)employee); } // or better introduce sort of type map } 

Another proper name is EmployeeProxy, as you prefer.

+8
source

What you are trying to do is called duck typing . You can do this using adapter classes and a common interface, but creating these adapters manually requires a lot of repeating glue code. One of the ways you might run into writing glue code is to dynamically build an adapter type. You can do this yourself through IL Emit (a useful exercise if you have never had the opportunity to play with it before, although several boundary cases may be enough to consider). If you are simply interested in making it work, however you can check this project as a place to start. The C # type 'dynamic' can also be used (and completes the same generation code behind the scenes), but it does not give you a link that you can pass to non-dynamic code as if it were an interface type.

+2
source

All Articles