2010-04-12 25 views

回答

0

編輯:請注意,此答案是在編輯完全更改問題之前給出的。正因爲如此,它現在提到的東西只是在最初陳述的問題中出現。我請你原諒所有的「懸掛指針」。 :-)


簡短的回答:

隨着你發佈的代碼,我沒有看到一個替代鑄造IFoo<T>。如果你不這樣做,編譯器會發出警告(至少在我的機器上)。

更復雜的答案:

請問您的代碼實際上必須要這樣呢?更具體地說,你是否首先需要演員陣容?

我以爲你會打電話給你的工廠方法或多或少是這樣的:

var stringFoo = FooFactory.CreateFoo<string>(); 

您必須提供(在這種情況下string)模板參數明確,因爲它不能從任何方法論證得出(在這種情況下,因爲實際上根本沒有)。顯然,工廠方法將返回一個IFoo<string>

現在,因爲你必須明確指定在運行時的類型,你也可以同樣寫:

var stringFoo = StringFoo.Create(); 

,因此具有內StringFoo工廠方法,這樣,無條件地做明顯:

public class StringFoo : IFoo<string> 
{ 
    ... 

    public static StringFoo Create() // or alternatively, return an IFoo<string> 
    { 
     return new StringFoo(); 
    } 
} 

通過應用這種模式對其他IFoo<T>實現過,這將節省您的if鏈或內部FooFactory.CreateFoo<T>switch塊,使你的代碼更容易,並擺脫必要投(你關心)。

不要誤解我的意思,我知道支持多個對象類型的工廠方法在某些情況下是有用;但在你的情況下它似乎會造成比它的價值更大的麻煩。


P.S:您可能會發現一些IoC容器有趣的一個方面。它們通常需要進行配置,這包括註冊抽象接口的具體類型(即實現類)的過程;例如(這裏使用Autofac):

var builder = new ContainerBuilder(); 
builder.RegisterType<StringFoo>().As<IFoo<string>>(); 

再後來,可以請求一個抽象類型的對象實例:

using (var container = builder.Build()) 
{ 
    var stringFoo = container.Resolve<IFoo<string>>(); 
    ... 
} 

Resolve方法是最有趣的部分。您提供一個抽象類型,並使用註冊類型,它將返回一個StringFoo類型的具體對象。仔細研究一下,如果它聽起來對你來說不夠過分! :-)

+0

致敬:如果我可以問,爲什麼? – stakx 2010-10-27 19:30:56

+0

@Merritt,不用擔心。畢竟,我們不是都在這裏學習嗎?我不介意寫下所有這些,因爲我覺得我也可以從寫作/解釋中獲益很多。 – stakx 2010-12-18 14:07:37

0

你能描述一下你用這個機制解決的問題嗎?最有可能有更清晰的方法來處理它。

編輯

是的,在代碼味道。您已將任何類型的空間都打開,除非您將其限制回單一類型,並生成運行時異常。爲什麼在這種情況下有一個類型參數?

+3

不,我不是。我不明白提供通用接口的抽象工廠的用處,但最終只會創建一個具體的具體類型。你所描述的是解決你尚未描述的問題。告訴我們這個問題是什麼,而不是你如何解決它的先入爲主的想法,我們將會更好地幫助你。 – 2010-04-12 17:37:50

+0

真空中的技術經常會導致尋找問題的解決方案。在沒有定義這種機制正在處理的情況下,你沒有任何標準可以作出價值判斷。如果您的問題更多地是爲了確定這種方法是否是針對某些問題的可行解決方案,那就不同了。我個人看不到通用工廠的用途,它不是通用的,並且在使用時會導致運行時異常。這就像製造一輛不會開始的汽車,除非你要去超市。 – 2010-04-12 18:41:16

0

你可以嘗試這樣的事情......

public static class FooFactory 
{ 
    private static readonly Dictionary<Type, Type> FooTypesLookup; 

    static FooFactory() 
    { 
     FooTypesLookup = (from type in typeof(FooFactory).Assembly.GetExportedTypes() 
          let fooInterface = 
          type.GetInterfaces().FirstOrDefault(
           x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IFoo<>)) 
          where fooInterface != null 
          let firstTypeArgument = fooInterface.GetGenericArguments().First() 
          select new { Type = type, TypeArgument = firstTypeArgument }) 
      .ToDictionary(x => x.TypeArgument, x => x.Type); 
    } 

    public static IFoo<T> CreateFoo<T>() 
    { 
     var genericArgumentType = typeof(T); 
     Type closedFooType; 
     return FooTypesLookup.TryGetValue(genericArgumentType, out closedFooType) 
       ? (IFoo<T>) Activator.CreateInstance(closedFooType) 
       : null; 
    } 
} 

或者更好的是,介紹自己喜歡的IoC容器(溫莎,結構圖等),以及登記,在那裏實現IFoo的所有類型和然後在需要時解析它們以取代Activator.CreateInstance調用。

+0

我的目標是不使用Activator.CreateInstance()。 – Merritt 2010-04-12 18:29:18

相關問題