在业务应用程序中使用反射可能存在的缺陷

时间:2010-01-26 22:19:56

标签: c# entity-framework reflection generics

尝试使用不同的方法并减少代码维护我最终使用反射在我的MDI应用程序中创建新表单。

这种“解决方案”的原因是提供一个设置新表单,实施安全检查和未来可能需求的中心位置。

我目前有一个使用MDI父窗体实例化的静态Activator类,每当我需要为应用程序创建设置新窗体时,我调用我创建的方法:private static T CreateForm<T>(params args[]) where T: class。此方法使用System.Activator类来实例化给定的类。我有其他静态方法,例如public static void ShowCustomers(),实际上通过调用CreateForm<frmCustomers>()来设置MDI父级等来使用'反射'方法。

对象创建发生在try / catch块中,如果无法创建表单,我会显示一条消息,以及原因。

到目前为止我所解释的可能无法验证是否需要使用反射在业务应用程序中创建MDI表单,但我希望在我的应用程序中添加另一个用途。我有一个实现ISupportInitialize接口的组件,当我将它放到表单上时,它执行安全检查并在EndInit方法中抛出System.Security.SecurityException。 CreateForm方法中存在此异常,并向用户显示用户友好消息。

此外,我在考虑可能存储MRU(最近使用过的)已创建表单的列表,并且比CreateForm方法更好地执行此操作。

我不熟悉代码气味,设计气味等术语,但我已经看到了经常使用的单词,但我的问题基本归结为:

鉴于我提供的信息(希望可以理解),这种方法是否闻起来“糟糕”?

如果是这样,哪种方法更适合?

欢迎任何评论。

谢谢, 斯蒂芬

public class Activator
{
    private static Activator instance;

    private MainForm mainForm;

    private Activator(MainForm mainForm)
    {
        this.mainForm = mainForm;
    }

    private Activator()
    {

    }         

    private static Activator Instance
    {
        get
        {
            if (instance == null) throw new Exception("Not activated");
            else return instance;
        }
    }

    private static void ShowMDIChild<T>(params object[] args) where T : class
    {
        try
        {
            System.Windows.Forms.Form frm = Create<T>(args) as System.Windows.Forms.Form;
            ShowMDIChild(frm);
        }
        catch (Exception e)
        {
            // Check if the inner exception is a security exception
            bool isSecurity = false;
            if (e.GetType().Equals(typeof(System.Security.SecurityException))) isSecurity = true;

            if (!isSecurity && e.InnerException != null && e.InnerException.GetType().Equals(typeof(System.Security.SecurityException))) isSecurity = true;

            if(isSecurity)
                MessageBox.Show(Instance.mainForm, "You do not have the neccessary privileges to access this resource", "Access denied", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Stop);
            else
                MessageBox.Show(Instance.mainForm, e.Message, "An error has occurred", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
        }
    }

    private static void ShowMDIChild(System.Windows.Forms.Form form)
    {
        Instance.mainForm.ShowMDIChild(form);
    }

    private static T Create<T>(params object[] args) where T: class
    {
        T result = System.Activator.CreateInstance(typeof(T), args) as T;

        return result;
    }

    public static void Register(MainForm mainForm)
    {
        instance = new Activator(mainForm);
    }

    public static void Customers()
    {
        ShowMDIChild<Forms.Customers>();
    }
}

3 个答案:

答案 0 :(得分:3)

你为自己建立了一个框架。它解决了您的问题,正如您所说,它减少了代码维护。如果您对代码感到满意,那么您就完成了。

好主意是记录它,以防你获得/雇佣更多的开发人员来处理这个项目。

答案 1 :(得分:1)

您可以将所有构造函数逻辑移动到类似IConstruct的接口实现,并向CreateForm添加另一个约束以允许类似这样的内容:

private static T CreateForm<T>(params object[] args) where T : class, new() {
    T t = new T();
    var construct = t as IConstruct;
    if (construct != null) {
        construct.Construct(args);
    }
    var initialize = t as IInitialize;
    if (initialize != null) {
        initialize.Initialize();
    }
    return t;
}

这将在没有反射的情况下实现相同的目标,但需要移动一些构造函数逻辑。

答案 2 :(得分:0)

如果它没有构造函数的参数,你可以这样做。如果不是这种情况,我发现您的设计没有问题,除非您遇到性能问题(我怀疑)。

public static TForm CreateForm<TForm>() where TForm : Form, new()
{
    return ProccessNewForm<TForm>(new TForm());
} 

public static TForm CreateForm<TForm>(Func<TForm, TForm> initializer) where TForm : Form, new()
{
    return ProccessNewForm<TForm>(initializer(new TForm()));
} 

private static TForm ProccessNewForm<TForm>(TForm newForm) where TForm : Form, new()
{
    // do stuff

    return newForm;
}