2012-12-07 33 views
0

我試圖手動滾動我自己的IoC工具。Activator.CreateInstance - 無法使用返回類型

這是國際奧委會的守則的一部分:

public static object Resolve(Type contract) 
{ 
    Type Implementation = typeSettings[contract]; 

    ConstructorInfo constructor = Implementation.GetConstructors()[0]; 

    ParameterInfo[] constructorParam = constructor.GetParameters(); 

    if (constructorParam.Length == 0) 
     Activator.CreateInstance(Implementation); 

    List<object> paramList = new List<object>(constructorParam.Length); 

    foreach(ParameterInfo param in constructorParam) 
     paramList.Add(Resolve(param.ParameterType)); 

    return constructor.Invoke(paramList.ToArray()); 
} 

我想回到泛型類型T的對象,我沒能做到這一點。

我無法對它進行轉換。我只使用一個接口和兩個依賴項。 (IPredictingFutureEartAndSkyPrediction,BadConnections

我試圖將它轉換爲接口類型。 (爲了訪問我的客戶代碼中的方法。)但是,這也沒有解決。

我錯過了什麼?

+1

「我無法對它進行轉換。」 - 爲什麼不?真的不清楚你想要做什麼,或者你爲什麼希望*能夠使用你在執行時只知道的類型成員...... –

+0

@JonSkeet,讓我添加更多的代碼來清除它。 – TheSilverBullet

回答

0

謝謝你們,爲響應。 我添加此重寫的解決方法

public static T Resolve<T>() { return (T)Resolve(typeof(T)); } 

現在,我得到正確的類型。這是客戶端代碼:

IPredictingFuture predictions; 
predictions = IoC.Resolve<IPredictingFuture>(); 

這樣,預測後的智能感知工作得很好。

如果有讀者在這個問題降落,因爲他們正試圖編造一個IoC容器,我想他們指出這些偉大的鏈接:

  1. 33 liner IoC by Ken
  2. 15 liner IoC by Ayende
  3. 跟進post by Ayende關於爲什麼你不應該編碼你自己的IoC
  4. Good link關於IoC容器
  5. Another SO question wh ich談到IoC
1

在你的方法中,contract只在運行時才知道,所以它不能在編譯時使用。根據您的來電,您可以將其更改爲一個泛型類型參數,在這種情況下,你可以這樣做:

public static object Resolve(Type contract) 
{ 
    Type Implementation = typeSettings[contract]; 

    ConstructorInfo constructor = Implementation.GetConstructors()[0]; 

    ParameterInfo[] constructorParam = constructor.GetParameters(); 

    if (constructorParam.Length == 0) 
     Activator.CreateInstance(Implementation); 

    List<object> paramList = new List<object>(constructorParam.Length); 

    foreach(ParameterInfo param in constructorParam) 
     paramList.Add(Resolve(param.ParameterType)); 

    return constructor.Invoke(paramList.ToArray()); 
} 

public static T Resolve<T>() 
{ 
    return (T)Resolve(typeof(T)); 
} 

因爲重載你提到,Resolve(Type)遞歸調用自己,和通用版本不能調用自身像那樣。

+0

我不認爲這會奏效。實際的代碼使用遞歸。它再次調用解析。 'paramList.Add(解析(param.ParameterType)); '。我正在嘗試超載Resolve now ... – TheSilverBullet

+0

@TheSilverBullet啊,我錯過了。是的,超載會解決這個問題,我會編輯。 – hvd

+0

@TheSilverBullet編輯,這樣你可以調用'Resolve ()',它在編譯時已知返回'IPredictingFuture',或者你可以調用'Resolve(typeof(IPredictingFuture))',它返回一個''你必須在來電者一側施放「物體」。 – hvd

0

調整這個場地的命名空間,我已經使用了多年......

using System; 
using System.Collections.Generic; 
using DataAccess.Core.DataInterfaces; 
using DataAccess.Core.Utils; 

namespace StackOverflowExample 
{ 
    public class SimpleIoC<T> 
    { 
     public T getInstance() 
     { 
      return getInstance(null); 
     } 

     public T getInstance(object[] initializationParameters) 
     { 
      Type type = Activator.CreateInstance(typeof(T), initializationParameters).GetType(); 
      // Any special initialization for an object should be placed in a case statement 
      // using that object's type name 
      switch (type.ToString()) 
      { 
       // Example 
       //case "DataAccess.Data.ApplicantDao": 
       // // - Do pre-instanciation initialization stuff here - 
       // return (T)Activator.CreateInstance(typeof(T), initializationParameters); 
       default: 
        return (T)Activator.CreateInstance(typeof(T), initializationParameters); 
      } 
     } 
    } 
} 

不知道這人會幫你,但我用這個作爲一個業務規則評估引擎的一部分。 ..

using System; 
using System.Collections.Generic; 
using System.Reflection; 
using System.Threading; 

namespace StackOverflowExample 
{ 
    public static class DynamicObjectFactory 
    { 
     private static readonly object _lock = new object(); 

     public static object getInstance(string assemblyName, string className) 
     { 
      Monitor.Enter(_lock); 
      try 
      { 
       System.Reflection.Assembly asm = System.Reflection.Assembly.Load(assemblyName); 
       return asm.CreateInstance(className, false, System.Reflection.BindingFlags.CreateInstance, null, null, null, null); 
      } 
      finally 
      { 
       Monitor.Exit(_lock); 
      } 
     } 

    public static object getInstance(string assemblyName, string className, object[] constructorParameters) 
    { 
     Monitor.Enter(_lock); 
     try 
     { 
      System.Reflection.Assembly asm = System.Reflection.Assembly.Load(assemblyName); 
      return asm.CreateInstance(className, false, System.Reflection.BindingFlags.CreateInstance, null, constructorParameters, null, null); 
     } 
     finally 
     { 
      Monitor.Exit(_lock); 
     } 
    } 
} 

}

相關問題