Возможные недостатки использования отражения в бизнес-приложении - PullRequest
3 голосов
/ 27 января 2010

Экспериментируя с использованием разных подходов и сокращая объем обслуживания кода, я в конечном итоге использовал рефлексию для создания новых форм в своем приложении MDI.

Причина этого «решения» состоит в том, чтобы предоставить центральное место для настройки новых форм, проведения проверок безопасности и возможных будущих потребностей.

В настоящее время у меня есть статический класс Activator, экземпляр которого создается родительской формой MDI, и всякий раз, когда мне нужно создать новые настройки для приложения, я вызываю созданный мной метод: private static T CreateForm<T>(params args[]) where T: class. Этот метод использует класс System.Activator для создания экземпляра данного класса. У меня есть другие статические методы, такие как public static void ShowCustomers(), которые в действительности используют метод «отражения», вызывая CreateForm<frmCustomers>(), который устанавливает родительский элемент MDI и т. Д.

Создание объекта происходит в блоке try / catch, и я показываю сообщение, если форма не может быть создана, и причины, по которым.

То, что я объяснил до сих пор, возможно, не подтверждает необходимость использования отражения для создания форм MDI в бизнес-приложении, но я хотел бы добавить еще одно использование, которое имеет это в моем приложении. У меня есть компонент, который реализует интерфейс ISupportInitialize, и когда я помещаю его в форму, он выполняет проверки безопасности и выдает исключение System.Security.SecurityException в метод EndInit. Это исключение применяется в методе CreateForm, и пользователю выводится удобное сообщение.

Кроме того, я подумывал о том, чтобы, возможно, сохранить MRU (последний использовавшийся) список созданных форм и где это лучше сделать, чем в методе CreateForm.

Я не знаком с такими терминами, как запах кода, дизайнерский запах или тому подобное, но я видел слова, используемые достаточно часто, но мой вопрос сводится к следующему:

Учитывая информацию, которую я предоставил (надеюсь, понятно), пахнет ли этот подход «плохо»?

Если так, какой подход лучше подходит?

Любые комментарии приветствуются.

Спасибо, Stefan

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 ]

3 голосов
/ 27 января 2010

Вы построили себе каркас. Это решает вашу проблему и, как вы сказали, уменьшает обслуживание кода. Если вам удобно с кодом, все готово.

Хорошей идеей было бы документировать это на тот случай, если вы привлечете / наймете больше разработчиков для работы над этим проектом.

1 голос
/ 27 января 2010

Вы можете переместить всю логику конструктора в реализацию интерфейса, такую ​​как 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;
}

Это позволит достичь тех же целей без размышлений, но требует перемещения некоторой логики конструктора.

0 голосов
/ 27 января 2010

Если у него нет параметров для конструктора, вы можете сделать что-то вроде этого. Если это не так, я не вижу проблем с вашим дизайном, если вы не столкнетесь с проблемами производительности ( Я сомневаюсь в этом ).

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...