在工厂模式中反射的通用方法

时间:2014-11-01 08:59:20

标签: c# generics reflection factory-pattern

我已将我的工厂发布到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;
    }
}

1 个答案:

答案 0 :(得分: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映射。

另一方面,如果你依赖一个字符串,找一个类型要困难得多。类型可以存在于不同的程序集中短名称可能还不够。使用完整类型名称(也包括程序集名称)来调用调用程序会使调用更加困难(调用者必须知道类型才能获得其全名)。