2014-09-05 87 views
6

我看到了類似於此的其他問題,但它沒有解決我的問題。一個問題的例子:Unity register generic type for non generic interfaceUnity無法解析通用存儲庫

我有接口

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。

我看到了許多不同的來源,他們都顯示了實現它的相同方式。爲什麼它不起作用?

UPDATE

這是實際執行:

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

您應該刪除檢查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; 
} 
+0

隨着你的更新,我明白了。所以它實際上註冊了通用的「版本」。我改變了代碼並添加了try-catch塊,現在它可以工作。我要求你在開始時刪除「= default(T)」,因爲我們應該指定默認值(T)來解決catch問題。然後,我會將您的答案設置爲解決方案。謝謝。 – Th3B0Y 2014-09-05 12:56:22

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(); 
    } 
} 
+0

枚舉當我使用的代碼exatly是你的,它的工作原理也是如此。我添加了我的實現(很簡單)。請看一下。 – Th3B0Y 2014-09-05 12:40:21

0

我喜歡Jehof & ThB0Y答案。但我不喜歡捕捉異常。我寫了自己的IsRegisteredInternal方法來檢查未解決的泛型。

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

     if (IsRegisteredInternal<T>()) 
     { 
      ret = Container.Resolve<T>(); 
     } 

     return ret; 
    } 

    private static bool IsRegisteredInternal<T>() 
    { 
     if (Container.IsRegistered<T>()) 
      return true; 
     if (typeof(T).IsGenericType) 
     { 
      return Container.IsRegistered(typeof(T).GetGenericTypeDefinition()); 
     } 
     return false; 
    } 

注:IsRegistered()通過Container.Registrations