Unity无法解析Generic存储库

时间:2014-09-05 12:13:30

标签: c# unity-container repository-pattern

我看到了类似的其他问题,但它并没有解决我的问题。一个问题的示例:Unity register generic type for non generic interface

我有界面

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

和班级

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

我注册了

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

并尝试解决它

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

它总是返回null。

我看到了许多不同的来源,他们都表现出相同的实现方式。为什么不起作用?

更新

这是实际的实施:

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);
    }
}

3 个答案:

答案 0 :(得分:3)

您应该删除代码中的检查if (Container.IsRegistered<T>()),因为这会为您请求的每个存储库返回false。像IRepository<string>IRepository<User>等混凝土存储库未在容器中仅注册IRepository<T>的通用版本。

如果要返回null,请在Container.Resolve周围使用try-catch-block,以便在出现异常时将其解析为null。

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

    //if (Container.IsRegistered<T>()) 
    try{
      resolved = Container.Resolve<T>();
    }
    catch(Exception){
      resolved = default(T);
    }
    return resolved;
}

答案 1 :(得分:2)

我用Unity做了这个小测试,试图理解你的问题(我不得不稍微改变GetById方法)。但是,它按预期工作,打印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();
    }
}

答案 2 :(得分:0)

我喜欢 Jehof&amp; ThB0Y 回答。但我不喜欢捕捉异常。我编写了自己的IsRegisteredInternal方法来检查未解析的泛型。

from lxml import html
h = html.fromstring('''<div id="outer">
<div id="inner" class="content body">
       text
</div></div>''')
content = h.cssselect('div.content')[0]
content.text    
# output :
# '\n       text\n'

from cssselect import GenericTranslator
GenericTranslator().css_to_xpath('div.content')    
# output :
# u"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' content ')]"

注意:IsRegistered()通过Container.Registrations枚举