2014-11-01 65 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