2008-11-20 18 views
2

我有一個通用函數,它將接口作爲類型獲取,現在在一種情況下,我必須根據接口創建一個新類。我一直在想它,解決這個問題的一種方法是使用IoC,但我希望會有另一種方式,因爲IoC看起來有點像矯枉過正。C# - 根據通用類中提供的接口實例化一個類

下面

是使用訪問者模式的嘗試:

public class RepositoryManager<T> : IRepositoryManager<T> where T : class, new() 
{ 
    public T GetOrCreate(string id) 
    { 
     T item = (T)CreateNew(new T(), id); 
     return item; 
    } 
} 

如果不是的界面我得到了一個對象,然後我可以使用訪問者模式找出實例化什麼類,但我似乎無法根據提供的接口來確定。

我有一個其他的想法是,如果我可以使聲明像一個或?

public class RepositoryManager<T> : IRepositoryManager<T> where T : class, Iabc or Ixyz, new() 

我希望這個問題是清楚:)

馬克


感謝您的答覆的。

的問題是,該方法可以有分配給它,例如很多不同的接口:

RepositoryManager類:

private static IMedicament CreateNew(IMedicament emptyType, string id) 
{ 
    return new Medicament { Id = id }; 
} 
private static IRefund CreateNew(IRefund emptyType, string id) 
{ 
    return new Refund { Id = id }; 
} 

RepositoryManager<Iabc> abcRepository = new RepositoryManager<Iabc>(); 
RepositoryManager<Ixyz> xyzRepository = new RepositoryManager<Ixyz>(); 

Iabc abc = abcRepository.GetOrCreate("12345"); 
Ixyz xyz = xyzRepository.GetOrCreate("12345"); 

所以使用T item = (T)CreateNew(new T(), id);不會工作,因爲我必須告訴它是t可以是Iabc或Ixyz類型,但是當我這樣做時,出現以下錯誤:

該調用在以下方法或屬性之間不明確:RepositoryManager<T>.CreateNew(IMedicament, string)RepositoryManager<T>.CreateNew(IRefund, string)

這將是很好,如果我得到這個工作,除了複製代碼幾次。

+1

我不明白你的問題是什麼。你想做什麼?編寫一個將接口作爲類型(參數?)並構造一個實現該接口的類的方法? (這將需要註冊表或反射搜索。)或其他東西? – 2008-11-20 00:29:07

回答

1

如果我明白你的問題是什麼,基本上你希望(從某種意義上)做RhinoMocks的工作,除了RhinoMocks實際上是從接口動態創建一個類的,而你想使用現有的類。

我對代碼並不熟悉,知道RhinoMocks是如何實現這個功能的,但是因爲它是開源的,所以你可能能夠得到一些想法,但是看看它的源代碼。

http://ayende.com/projects/rhino-mocks/downloads.aspx

0

我碰到這個問題就自己只是一天。探針是你不知道構造函數需要多少個參數。假設它沒有,下面的代碼將工作。

public void Method<T>() 
{ 
    Type type = typeof(T); 

    T newObject = (T)type.GetConstructor(new System.Type[] { }).Invoke(new object[] { }); 
} 

該示例使用反射。如果您需要參數,則可以將對象放入代碼中創建的數組中。

2

爲什麼不工作?

public class RepositoryManager<T> : IRepositoryManager<T> where T : Ixyz, new() 
{ 
    public T GetOrCreate(string id) 
    { 
     T item = (T)CreateNew(new T(), id); 
     return item; 
    } 
} 

的選擇,如果您不能使用新的()是在代表傳遞到創建對象(或兼容型):

public class RepositoryManager<T> : IRepositoryManager<T> where T : Ixyz 
{ 
    private Func<T> _tConstructor; 

    public RepositoryManager(Func<T> tConstructor) 
    { 
     this._tConstructor = tConstructor; 
    } 

    public T GetOrCreate(string id,) 
    { 
     T item = (T)CreateNew(this._tConstructor(), id); 
     return item; 
    } 
} 
2

我不知道我的理解這個問題已經完全解決了,但是我之前用過這樣的東西

public class Repository 
{ 
    public T Create<T>(string id) where T : class 
    { 
     return Activator.CreateInstance(typeof(T), new[] { id }) as T; 
    } 
} 
1

如何使IRefund和IMedicament實現共享接口,它們都具有Id屬性?

0

也許以下幾種可能適合你? 1)創建一個字典,其中類型是你的接口(T參數),對象是可以創建的對象的虛擬實例,2)讓你的虛擬對象成爲實現T的新對象的工廠。

您的RepositoryManager只需要使用受支持的界面 - 對象對來初始化字典,其中多個界面可映射到相同的對象(如果需要)。