Randel Ramirez
Randel Ramirez

Reputation: 3761

How does Adapter Design Pattern work in C#?

I have here an example of an adapter pattern(Yes you can check if it was implemented properly), but my real question is here, it is said that Adapter Design Pattern does the following: "Converts the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces." But I'm a bit confused on that statement, I don't quite get so based on my code below, I want to know where it occurred.

Here are my classes/Interface:

public interface ILogger
{
      void Write(string data);
}

public class InfrastructureDebugLogger : ILogger
{
      public void Write(string data)
      {
           Debug.WriteLine(data);
      }
}

public class InfrastructureLoggerToDatabaseAdapter : ILogger
{
      private IRepository<Log> adaptee;

      public InfrastructureLoggerToDatabaseAdapter(IRepository<Log> adaptee)
      {
            this.adaptee = adaptee;
      }

      public void Write(string data)
      {
            var log = new Log() { Value = data };
            adaptee.Create(log);   
      }
}

public interface IRepository<T>
{
        void Create(T item);
        void Update(T item);
        T Find(int id);

}

public class Log
{
        public int ID { get; set; }
        public string Value { get; set; }
}

public class LogRepository : IRepository<Log>
{
        public void Create(Log item)
        {
            Console.WriteLine("Created an item inside the LogRepository");
        }

        public void Update(Log item)
        {
            throw new NotImplementedException();
        }

        public Log Find(int id)
        {
            throw new NotImplementedException();
        }
}

class Program
{
    static void Main(string[] args)
    {

            ILogger logger = new InfrastructureDebugLogger();
            Console.Write("Data: ");
            string data = Console.ReadLine();
            logger.Write(data);
            InfrastructureLoggerToDatabaseAdapter loggerToDatabaseAdapter = 
                new InfrastructureLoggerToDatabaseAdapter(new LogRepository());
            loggerToDatabaseAdapter.Write(data);
            Console.ReadKey();
     }
 }

Upvotes: 2

Views: 1230

Answers (4)

tusharmath
tusharmath

Reputation: 10992

To put it in simple words -

  1. Rename your adapter because its not really a InfrastructureLoggerToDatabaseAdapter instead its a Repository to Logger type. Since you are passing a IRepository type object and expecting it to behave like an ILogger.

  2. Since the repository have now been updated converted into an ILog type object you should use an ILogger variable to operate on it.

Code:

public class RepositoryToLoggerAdapter : ILogger
    {
        private IRepository adaptee;

        public InfrastructureLoggerToDatabaseAdapter(IRepository adaptee)
        {
            this.adaptee = adaptee;
        }

        public void Write(string data)
        {
            var log = new Log() { Value = data };
            adaptee.Create(log);   
        }
    }

class Program
    {
        static void Main(string[] args)
        {

            ILogger logger = new InfrastructureDebugLogger();
            Console.Write("Data: ");

            string data = Console.ReadLine();

      //This step is redundant as the text will be shown on the screen as you type
logger.Write(data);

//Create an object of IRepository type.
IRepository repository= new LogRepository();

//The create method works as it should
repository.Create(data);


//You could not have stored the repository object in the logger variable if you did not have this adapter.

            logger = new RepositoryToLoggerAdapter(repository);

//Effectively you now are calling the Create method of the Repository by calling the Write method of the logger.

            logger.Write(data);
            Console.ReadKey();
        }
    }

Hope this makes sense. Let me know if something is not clear.

Upvotes: 2

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236208

That's not clear from your example, because you don't have clients which require logger. Consider following class:

public class Foo
{
    private ILogger _logger;

    public Foo(ILogger logger)
    {
         _logger = logger;
    }

    public void Bar()
    {
       _logger.Write("Bar is called");
       // do something
    }
}

You can't pass LogRepository to this class. Because LogRepository does not implement ILogger interface. But with adapter you can 'convert' IRepository<Log> interface to ILogger interface required by Foo class:

class Program
{
    static void Main(string[] args)
    {
        // you can't pass repository to Foo
        LogRepository repository = new LogRepository();            

        InfrastructureLoggerToDatabaseAdapter loggerToDatabaseAdapter = 
            new InfrastructureLoggerToDatabaseAdapter(repository);

        // but you can pass adapter
        Foo foo = new Foo(loggerToDatabaseAdapter);
        foo.Bar();

        Console.ReadKey();
    }
}

Actual work still done by LogRepository class. Adapter just adapts it's interface to interface required by client. Same way outlet adapters work. If you have electric razor which should be plugged into US outlet, you can't use it in Europe without adapter.

Upvotes: 0

weston
weston

Reputation: 54781

Converts the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.

In this case you have an IRepository<Log>, but you need to to be an ILogger, i.e. "another interface clients expect". The adaptor class allows this by encapsulating the IRepository<Log> and translating ILogger calls into IRepository<Log> calls.

Upvotes: 1

Reed Copsey
Reed Copsey

Reputation: 564373

Your code shows the adapter, but doesn't show using it as an adapter.

In order to use this adapter, you'd need to use your LogRepository, which implements IRepository<Log>, as an ILogger via the adapter. Something like:

class Program
{
    static void Main(string[] args)
    {

        Console.Write("Data: ");
        string data = Console.ReadLine();
        InfrastructureLoggerToDatabaseAdapter loggerToDatabaseAdapter = 
            new InfrastructureLoggerToDatabaseAdapter(new LogRepository());

        // Here, you're using a IRepository<Log>, but adapting it to be used as an ILogger...
        ILogger logger = loggerToDatabaseAdapter;
        logger.Write(data);
        Console.ReadKey();
    }
}

Upvotes: 3

Related Questions