Chris Wohlert
Chris Wohlert

Reputation: 600

How to adapt to and from an external class

I retrieve an object from an external library, later on I need to return this object back to the library. Here's an example:

var user = dao.GetUser();
var team = dao.GetTeam();
team.Add(user);

I have already tried the following:

It looks like this:

var user = new UserAdapter(dao.GetUser());
var team = new TeamAdapter(dao.GetTeam());
team.Add(new ExternalUserAdapter(user));

The problem was, my internal interface now had to supply a vast number of methods that I didn't need since ExternalUserAdapter implements the external interface which is far bigger than I'd like.

I have also tried the N-Way-Adapter or Class Adapter pattern, but that didn't work, since I cannot convert an external user to an internal class adapter, ie. can't convert a cat to a dog just because they are both animals.

How can I solve this issue? I would love some blog, article or book reference addressing this issue

Upvotes: 0

Views: 482

Answers (2)

Larry Dukek
Larry Dukek

Reputation: 2199

I assume you are writing your code as a service and therefore the decoupling makes complete sense. I am afraid there are only two good ways to completely decouple your code from the third party's.

One would be for your class's fields to completely match the third parties fields, otherwise you won't be able to reconstruct the user object before adding it to the team. This is of course the exact thing you stated as an issue you wanted to avoid.

The other would be to have your user wrapper contain just enough information to get the user and team before the addition to the team.

I will demonstrate in the code below using a helper class to convert back and fourth and with a few assumptions:

  • dao.GetUser() creates a new user
  • dao.GetUser(int) would finds an existing user by id
  • dao.GetTeam(string) finds a team by name
  • dao.GetTeam(int) finds a team by id

Helper Class (Replace :

public static class ThirdPartyHelpers
  {
    private static readonly ThirdParty.Dao dao = new ThirdParty.Dao();

    public static ThirdParty.User GetUser()
    {
      return dao.GetUser();
    }

    public static ThirdParty.Team GetTeam()
    {
      return dao.GetTeam();
    }

    public static User Decoupled(this ThirdParty.User user)
    {
      var myUser = new User();
      myUser.Id = user.Id;
      myUser.Name = user.FirstName + " " + user.LastName;

      return myUser;
    }

    public static ThirdParty.User ToThirdParty(this User user)
    {
      var thierUser = dao.GetUser(user.Id);
      return thierUser;
    }

    public static Team Decoupled(this ThirdParty.Team team)
    {
      var myTeam = new Team();
      myTeam.Id = team.Id;
      myTeam.Name = team.Name;

      return myTeam;
    }

    public static ThirdParty.Team ToThirdParty(this Team team)
    {
      var theirTeam = dao.GetTeam(team.Id);
      return theirTeam;
    }
  }

Very thin classes for your object:

 public class Team
  {
    public int Id { get; set; }
    public object Name { get; set; }
  }

  public class User
  {
    public int Id { get; set; }
    public string Name { get; set; }
  }

Then your code would look like this:

  var user = ThirdPartyHelpers.GetUser().Decoupled();
  var team = ThirdPartyHelpers.GetTeam().Decoupled();

  team.ToThirdParty().Add(user.ToThirdParty());

Hopefully this will get you going in

Upvotes: 1

Kell
Kell

Reputation: 3317

Why can't you do this?

    var user = dao.GetUser() as IUserAdapter;
    var team = dao.GetTeam() as ITeamAdapter;
    team.Add(user as TheActualUnderlyingClassReturnedFromGetUser);

You'll need to define the IUserAdapter and ITeamAdapter interfaces of course but won't have to write any code or write any function signatures for the methods you don't use.

Edited after my brain-fart:

public class UserAdapter
{
    public ExternalUser refToUser {get; private set;}
    //expose the methods you need here
    //eg:
    public void SomeMethod(int someParameter)
    {
        refToUser.SomeMethod(someParameter);
    }
    public UserAdapter(ExternalUser usr)
    {
    refToUser = usr;
    }
}

Upvotes: 0

Related Questions