Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity can't resolve Generic repository

I saw other questions similar to this, but it did not solve my problem. Example of one question: Unity register generic type for non generic interface

I have the interface

    public interface IRepository<T>
    {
        T GetById(int id);
    }

and the class

    public class Repository<T> : IRepository<T>
    {
         public T GetById(int id)
         {
             Console.WriteLine("Type: " + GetType());
             return default(T);
         }
    }

I register it

    Container.RegisterType(typeof(IRepository<>), typeof(Repository<>));

and try to resolve it

    IRepository<string> IRepository = Container.Resolve<IRepository<string>>();

It always returns null.

I saw many different sources and they all show the same way of implementing it. Why does it not work?

UPDATE

This is the actual implementation:

public class Program
{
    static Program()
    {
        DIDefaultRegisters.Initialize();
    }

    public static void Main(string[] args)
    {
        var iRepository = UnityDIFacade.Resolve<IRepository<string>>();

        iRepository.GetById(1);
    }
}

public class DIDefaultRegisters
{
    public static void Initialize()
    {
        Register(typeof(IRepository<>),typeof(Repository<>));
    }

    private static void Register(Type from, Type to)
    {
        UnityDIFacade.RegisterType(from, to);
    }
}

public class UnityDIFacade
{
    private static readonly IUnityContainer Container;

    static UnityDIFacade()
    {
        IUnityContainer container = new UnityContainer();

        var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
        if (section != null)
            section.Configure(container);

        Container = container;
    }

    public static T Resolve<T>()
    {
        T resolved = default(T);

        if (Container.IsRegistered<T>()) 
            resolved = Container.Resolve<T>();

        return resolved;
    }

    public static void RegisterType(Type from, Type to)
    {
        Container.RegisterType(from, to);
    }
}
like image 810
Th3B0Y Avatar asked Sep 05 '14 12:09

Th3B0Y


2 Answers

You should remove the check if (Container.IsRegistered<T>()) in your code, cause this will return false for each repository you request. The concret repositories like IRepository<string>, IRepository<User> etc. are not registered in the container only the generic version of IRepository<T>.

If you want to return null, then use a try-catch-block around Container.Resolve to set resolved to null in case of an exception.

public static T Resolve<T>()
{
    T resolved;

    //if (Container.IsRegistered<T>()) 
    try{
      resolved = Container.Resolve<T>();
    }
    catch(Exception){
      resolved = default(T);
    }
    return resolved;
}
like image 64
Jehof Avatar answered Nov 12 '22 01:11

Jehof


I made this small test with Unity to try to understand your problem (I had to change the GetById method a bit). However, it works just as expected, prints Type: System.DateTime

public interface IRepository<T>
{
    T GetById(int id);
}
public class Repository<T> : IRepository<T>
{
    public T GetById(int id)
    {
        Console.WriteLine("Type: " + typeof(T));
        return default(T);
    }
}

class Program
{
    static void Main(string[] args)
    {
        var container = new UnityContainer();
        container.RegisterType(typeof(IRepository<>), typeof(Repository<>));

        IRepository<DateTime> iRepository = container.Resolve<IRepository<DateTime>>();

        iRepository.GetById(4);
        Console.ReadLine();
    }
}
like image 21
AndreySarafanov Avatar answered Nov 12 '22 01:11

AndreySarafanov