9) EvalManager

접근성 평가 도우미 프로그램은 평가자와 상호작용하는 폼과 엔진 사이에 관계를 느슨하게 하여 유지 보수 비용을 줄일 수 있게 개발합시다. 이를 위해 평가자의 명령을 받아 엔진에게 전달하는 부분이 필요한데 이러한 명령을 받아 평가 엔진을 제어 및 관리하는 EvalManager 클래스를 정의합시다.

class EvalManager
{

EvalManager 클래스 형식의 개체는 프로세스에 유일해야 서로 다른 폼들 사이의 명령을 하나의 개체에서 집중 관리할 수 있습니다. 이러한 부분의 신뢰성을 위해 단일체 패턴을 적용할게요. 유일한 단일체 개체를 위한 정적 멤버를 선언합니다.

    static EvalManager singleton;

단일체 멤버를 가져오기 할 수 있는 정적 속성을 제공합니다.

    public static EvalManager Manager
    {
        get{    return singleton;    }
    }
    static EvalManager()
    {

정적 생성자에서 단일체를 생성합니다.

        singleton = new EvalManager();

평가 보고서의 템플릿 형식 문서를 보관할 디렉토리를 생성합니다.

        Directory.CreateDirectory(cfg_dir);

템플릿 문서에 기록할 정보를 데이터 테이블을 이용합니다.

        DataTable dt = new DataTable("UI 속성");

테이블에 평가 항목들을 컬럼으로 추가합니다. 평가 점수를 기록할 컬럼을 추가합니다.

        dt.Columns.Add("EVALUATEVALUE",typeof(string));

접근성 속성들을 기록할 컬럼을 추가합니다.

        dt.Columns.Add("ACCELERATORKEY", typeof(string));

…중략…

접근성 컨트롤 패턴을 기록할 컬럼을 추가합니다.

        dt.Columns.Add("DOCK", typeof(string));

…중략…

접근성 요소 정보를 래핑한 EHAutoElem 개체를 기록할 컬럼을 추가합니다.

        dt.Columns.Add("EHAutoElem", typeof(EHAutoElem));

템플릿 문서를 XML 스키마 파일로 저장합니다.

        dt.WriteXmlSchema(cfg_dir + CFGPropertyTableName + ".xsd");
    }

단일체 패턴으로 제공할 것이므로 생성자는 접근 설정을 private으로 지정합니다.

    EvalManager()
    {

평가 프로젝트들을 보관할 컬렉션을 생성합니다.

        project_dic = new Dictionary<string, AccEvalProject>();
    }

평가 프로젝트를 생성을 게시할 이벤트와 프로젝트 변경을 게시할 이벤트를 선언합니다.

    public event MakeProjectEventHandler MakedProject = null;
    public event MakeProjectEventHandler ChangedProject = null;

평가 보고서의 템플릿 문서를 보관할 디렉토리와 테이블 이름를 상수로 선언합니다.

    const string cfg_dir = "./Configure/";
    public const string CFGPropertyTableName = "UI 속성";

현재 선택한 평가 프로젝트를 기억하는 멤버를 선언합니다.

    AccEvalProject currentpro = null;

평가 프로젝트들을 보관할 컬렉션 멤버를 선언합니다.

    Dictionary<string, AccEvalProject> project_dic;

평가 프로젝트들의 정보를 보관할 DataSet 개체를 선언합니다.

    DataSet project_ds = new DataSet();

평가 프로젝트들의 정보를 보관한 DataSet 개체를 가져오기 할 수 있게 속성을 제공합시다.

    public DataSet ProjectDataSet
    {
        get{    return project_ds;    }
    }

현재 선택한 프로젝트의 정보를 보관한 DataTable을 가져오기 할 수 있는 속성을 제공합시다.

    public DataTable ProjectTable
    {
        get{    return currentpro.Table;    }
    }

평가 프로젝트 개수를 가져오기 할 수 있는 속성을 제공합시다.

    public int ProjectCount
    {
        get{    return ProjectDataSet.Tables.Count;    }
    }

현재 평가 프로젝트를 가져오기 할 수 있는 속성을 제공합니다.

    public AccEvalProject CurrentProject
    {
        get{    return currentpro;    }
    }

현재 평가 프로젝트 제목을 가져오기 할 수 있는 속성을 제공합니다.

    public string ProjectTitle
    {
        get{    return currentpro.Title;    }
    }

현재 프로젝트를 설정하는 메서드를 제공합니다.

    public void SetCurrentProject(string title)
    {
        try
        {

프로젝트 사전 컬렉션에서 입력 인자로 받은 제목의 프로젝트를 현재 프로젝트로 설정합니다.

            currentpro = project_dic[title];

현재 프로젝트를 변경 이벤트를 게시합니다.

            if (ChangedProject != null){
                ChangedProject(this, new MakeProjectEventArgs(currentpro));
            }
        }
        catch { }
    }

평가 프로젝트를 비동기식으로 만들기 위해 대리자를 정의합시다.

    delegate void MakeProjectDele(string title, EHProcess ehprocess,
                                 AddFindElementDele find_dele, EHAutoElem eae);
    public void MakeProjectAsync(string title, EHProcess ehprocess, AsyncCallback EndProcess,
                                AddFindElementDele find_dele, EHAutoElem eae)
    {

비동기식으로 처리할 대리자를 생성합니다.

        MakeProjectDele dele = new MakeProjectDele(MakeProject);

대리자의 위임한 메서드를 비동기식으로 수행합니다.

        dele.BeginInvoke(title, ehprocess, find_dele, eae, EndProcess, null);
    }
    public void MakeProject(string title, EHProcess ehprocess,
                           AddFindElementDele find_dele, EHAutoElem eae)
    {

프로젝트에 사용할 DataTable 개체를 생성합니다.

        DataTable dt = new DataTable();

템플릿 문서의 스키마를 읽어와서 테이블의 컬럼을 형성합니다.

        dt.ReadXmlSchema(cfg_dir + CFGPropertyTableName + ".xsd");

테이블의 이름은 프로젝트 제목으로 설정합니다.

        dt.TableName = title;

전체 프로젝트 DataTable 개체를 보관하는 DataSet 개체에 보관합니다.

        ProjectDataSet.Tables.Add(dt);

평가 프로젝트 정보를 기억할 AccEvalProject 개체를 생성합니다.

        currentpro = new AccEvalProject(title,  dt, ehprocess);

현재 프로젝트의 정보 수집이 끝났을 때 처리하기 위한 이벤트 핸들러를 등록합니다.

        currentpro.EndEvalProject += new EventHandler(currentpro_EndEvalProject);

전체 프로젝트를 관리하는 사전 컬렉션에 현재 프로젝트를 보관합니다.

        project_dic[title] = currentpro;

현재 프로젝트의 정보를 검색하는 프로세스 모드를 초기화합니다.

        currentpro.InitProcessMode(find_dele);

프로젝트 생성 이벤트를 구독자가 있으면 이벤트를 게시합니다.

        if (MakedProject != null){  MakedProject(this, new MakeProjectEventArgs(currentpro));  }
    }
    void currentpro_EndEvalProject(object sender, EventArgs e)
    {

첫번째 입력 인자를 AccEvalProject 형식으로 참조합니다.

        AccEvalProject aep = sender as AccEvalProject;
        if (aep != null)
        {

사전 개체와 DataSet 개체에서 제거하고 현재 프로젝트를 null로 설정합니다.

            project_dic.Remove(aep.Title);
            projectDataSet.Tables.Remove(aep.Title);
            currentpro = null;

현재 프로젝트 선택 변경 이벤트의 구독자가 있으면 게시합니다.

            if (ChangedProject != null){ ChangedProject(this, new MakeProjectEventArgs(null)); }
        }
    }

 }
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
namespace 접근성_평가_도우미
{
    class EvalManager
    {
        static EvalManager singleton;
        public static EvalManager Manager
        {
            get{    return singleton;    }
        }
        static EvalManager()
        {
            singleton = new EvalManager();
            Directory.CreateDirectory(cfg_dir);
            DataTable dt = new DataTable("UI 속성");
            dt.Columns.Add("EVALUATEVALUE",typeof(string));
            dt.Columns.Add("ACCELERATORKEY", typeof(string));
            dt.Columns.Add("ACCESSKEY", typeof(string));
            dt.Columns.Add("AUTOMATIONID", typeof(string));
            dt.Columns.Add("BOUNDINGRECTANGLE", typeof(string));
            dt.Columns.Add("CLASSNAME", typeof(string));
            dt.Columns.Add("CONTROLTYPE", typeof(string));
            dt.Columns.Add("FRAMEWORKID", typeof(string));
            dt.Columns.Add("HASKEYBORDFOCUS", typeof(string));
            dt.Columns.Add("HELPTEXT", typeof(string));
            dt.Columns.Add("ISCONTENTELEMENT", typeof(string));
            dt.Columns.Add("ISCONTROLELEMENT", typeof(string));
            dt.Columns.Add("ISENABLE", typeof(string));
            dt.Columns.Add("ISKEYBOARDFOCUSABLE", typeof(string));
            dt.Columns.Add("ISOFFSCREEN", typeof(string));
            dt.Columns.Add("ISPASSWORD", typeof(string));
            dt.Columns.Add("IS_REQUIREDFORFORM", typeof(string));
            dt.Columns.Add("ITEMSTATUS", typeof(string));
            dt.Columns.Add("ITEMTYPE", typeof(string));
            dt.Columns.Add("LABLEDBY", typeof(string));
            dt.Columns.Add("LOACLIZEDCONTROLTYPE", typeof(string));
            dt.Columns.Add("NAME", typeof(string));
            dt.Columns.Add("NATIVEWINDOWHANDLE", typeof(string));
            dt.Columns.Add("ORIENTATION", typeof(string));
            dt.Columns.Add("PROCESSID", typeof(string));
            dt.Columns.Add("DOCK", typeof(string));
            dt.Columns.Add("EXPANDCOLLAPSE", typeof(string));
            dt.Columns.Add("GRID", typeof(object));
            dt.Columns.Add("GRIDITEM", typeof(object));
            dt.Columns.Add("INVOKE", typeof(object));
            dt.Columns.Add("MULTIPLEVIEW", typeof(object));
            dt.Columns.Add("RANGEVALUE", typeof(object));
            dt.Columns.Add("SCROLL", typeof(object));
            dt.Columns.Add("SCROLLITEM", typeof(object));
            dt.Columns.Add("SELECTION", typeof(object));
            dt.Columns.Add("SELECTIONITEM", typeof(object));
            dt.Columns.Add("TABLE", typeof(object));
            dt.Columns.Add("TABLEITEM", typeof(object));
            dt.Columns.Add("TEXT", typeof(object));
            dt.Columns.Add("TOGGLE", typeof(object));
            dt.Columns.Add("TRANSFORM", typeof(object));
            dt.Columns.Add("VALUE", typeof(object));
            dt.Columns.Add("WINDOW", typeof(object));
            dt.Columns.Add("EHAutoElem", typeof(EHAutoElem));
            dt.WriteXmlSchema(cfg_dir + CFGPropertyTableName + ".xsd");
        }
        EvalManager()
        {
            project_dic = new Dictionary<string, AccEvalProject>();
        }
        public event MakeProjectEventHandler MakedProject = null;
        public event MakeProjectEventHandler ChangedProject = null;
        const string cfg_dir = "./Configure/";
        public const string CFGPropertyTableName = "UI 속성";        
        AccEvalProject currentpro = null;
        Dictionary<string, AccEvalProject> project_dic = new Dictionary<string, AccEvalProject>();
        DataSet project_ds = new DataSet();

        public DataSet ProjectDataSet
        {
            get{    return project_ds;    }
        }
        public DataTable ProjectTable
        {
            get{    return currentpro.Table;    }
        }
        public int ProjectCount
        {
            get{    return ProjectDataSet.Tables.Count;    }
        }
        public AccEvalProject CurrentProject
        {
            get{    return currentpro;    }
        }
        public string ProjectTitle
        {
            get{    return currentpro.Title;    }
        }
        public void SetCurrentProject(string title)
        {
            try
            {
                currentpro = project_dic[title];
                if (ChangedProject != null)
                {
                    ChangedProject(this, new MakeProjectEventArgs(currentpro));
                }
            }
            catch { }
        }
        delegate void MakeProjectDele(string title, EHProcess ehprocess, 
                                    AddFindElementDele find_dele, EHAutoElem eae);
        public void MakeProjectAsync(string title, EHProcess ehprocess, 
               AsyncCallback EndProcess, AddFindElementDele find_dele, EHAutoElem eae)
        {
            MakeProjectDele dele = new MakeProjectDele(MakeProject);
            dele.BeginInvoke(title, ehprocess, find_dele, eae, EndProcess, null);
        } 
        public void MakeProject(string title, EHProcess ehprocess, 
                              AddFindElementDele find_dele, EHAutoElem eae)
        {
            DataTable dt = new DataTable();
            dt.ReadXmlSchema(cfg_dir + CFGPropertyTableName + ".xsd");
            dt.TableName = title;
            ProjectDataSet.Tables.Add(dt);
            currentpro = new AccEvalProject(title,  dt, ehprocess);
            currentpro.EndEvalProject += new EventHandler(currentpro_EndEvalProject); 
            project_dic[title] = currentpro;
            currentpro.InitProcessMode(find_dele);
            if (MakedProject != null)
            {
                MakedProject(this, new MakeProjectEventArgs(currentpro));
            }
        }
        void currentpro_EndEvalProject(object sender, EventArgs e)
        {
            AccEvalProject aep = sender as AccEvalProject;
            if (aep != null)
            {
                project_dic.Remove(aep.Title);
                ProjectDataSet.Tables.Remove(aep.Title);
                currentpro = null;
                if (ChangedProject != null)
                {
                    ChangedProject(this, new MakeProjectEventArgs(null));
                }
            }
        }
    }
}

[소스 10.9] EvalManager.cs