2014-11-01 28 views
0

我已經發布了我廠codereview.so現在我有這樣的:在工廠模式的反思泛型方法

public class WpfControlFactory 
{ 
    public static TControl CreateWpfControl<TControl>(string name = null) where TControl : class, IWpfControl 
    { 
     TControl wpfControl = default(TControl); 

     //Avoid some bone-headed exceptions 
     if (!typeof(TControl).IsAbstract) 
     { 
      wpfControl = Activator.CreateInstance<TControl>(); 
     } 

     if (wpfControl != null) 
     { 
      wpfControl.Name = name ?? Consts.DefaultEaControlName; 
     } 

     return wpfControl; 
    } 
} 

但不幸的是,我不能使用CreateWpfControl<TControl>()因爲我沒有TControl我已經做只有typeName字符串。

我讀過this所以我知道如何用反射來創建泛型方法。但實際上我不知道我應該在哪裏創建它。在這樣的工廠:

public static IWpfControl CreateWpfControl(string controlType, string controlName) 
    { 
     Type type = FindType(controlType); 
     if (type == null) 
     { 
      return null; 
     } 

     MethodInfo method = typeof(WpfControlFactory).GetMethod("CreateInstance"); 
     MethodInfo generic = method.MakeGenericMethod(type); 
     return (IWpfControl)generic.Invoke(null, null); 
    } 

    private static Type FindType(string typeName) 
    { 
     Type type = null; 
     WpfControl wpfControl; 
     Enum.TryParse(typeName, out wpfControl); 
     if (wpfControl != default(WpfControl)) 
     { 
      type = Type.GetType(typeName); 
     } 

     return type; 
    } 

    private static TControl CreateInstance<TControl>(string name = null) where TControl : class, IWpfControl 
    { 
     TControl wpfControl = default(TControl); 

     //Avoid some bone-headed exceptions 
     if (!typeof(TControl).IsAbstract) 
     { 
      wpfControl = Activator.CreateInstance<TControl>(); 
     } 

     if (wpfControl != null) 
     { 
      wpfControl.Name = name ?? Consts.DefaultEaControlName; 
     } 

     return wpfControl; 
    } 

或者在哪裏?我想我的課是符合SOLID

編輯

下一個可能的版本:

public class WpfControlFactory 
{ 
    public static IWpfControl CreateWpfControl(string controlType, string controlName = null) 
    { 
     IWpfControl wpfControl = default(IWpfControl); 

     Type type = Type.GetType(controlType); 
     if (type != null && type.IsAssignableFrom(typeof(IWpfControl))) 
     { 
      wpfControl = (IWpfControl)Activator.CreateInstance(type); 
     } 

     if (wpfControl != null) 
     { 
      wpfControl.Name = controlName ?? Consts.DefaultEaControlName; 
     } 

     return wpfControl; 
    } 
} 
+2

你能說一下'Enum.TryParse'這行嗎?我無法理解。另外,我不明白爲什麼你堅持重用泛型版本。掌握類型名稱後,可以使用'CreateInstance'的另一個重載,它接受類型名稱作爲字符串。 – 2014-11-01 10:00:32

+0

@WiktorZychla我有支持的控件的枚舉,這很重要,因爲我正在編寫插件到Enterprise Architect,我不支持它提供的所有控件。所以我檢查我的controlType是否支持類型。在第一篇文章中編輯版本。 – 2014-11-01 10:24:57

回答

0

你的第二個方法是行不通的,你不能讓類型了controlName的。我的想法是,如果你已經有一個封閉的枚舉,利用它。

public class WpfControlFactory 
{ 
    public static IWpfControl CreateWpfControl(WpfControl control, string controlName) 
    { 
    IWpfControl wpfControl = default(IWpfControl); 

    Type type = GetControl(control); 
    if (type != null && type.IsAssignableFrom(typeof(IWpfControl))) 
    { 
     wpfControl = (IWpfControl)Activator.CreateInstance(type); 
    } 

    if (wpfControl != null) 
    { 
     wpfControl.Name = controlName ?? Consts.DefaultEaControlName; 
    } 

    return wpfControl; 
    } 

    private Type GetControl(WpfControl control) 
    { 
    switch (control) 
    { 
     case WpfControl.Foo : return typeof(FooControlType); 
     ... 
    } 
    } 
} 

這樣你就可以在枚舉值和控件類型之間有一個乾淨的1-1映射。

另一方面,如果你依賴一個字符串,找到一個類型就困難得多。類型可以存在於不同的組件中。簡短的類型名稱可能還不夠。並且使用完整類型名稱(也包含程序集名稱)使調用者更加困難(調用者必須知道類型以獲取其全名)。

+0

在開始的時候,我也試着用'swich case'的方法,但[codereview.so](http://codereview.stackexchange.com/questions/68559/factory-pattern-with-controls)不是很滿意。 我知道創建類型限制,並且我想要創建的所有控件與工廠都在同一個程序集中。所以我認爲短式就夠了。 – 2014-11-01 11:05:12