다양한 소스 유형 및 다양한 대상 유형으로 데이터를 가져 오기위한 디자인 패턴


14

다음을 처리 할 수있는 가져 오기 스크립트 (C #로)를 디자인하고 빌드해야합니다.

  • 다양한 소스 (XML, XSLX, CSV)에서 데이터 읽기
  • 데이터 확인
  • 다양한 객체 유형 (고객, 주소)에 데이터 쓰기

데이터는 여러 소스에서 제공되지만 소스는 항상 하나의 가져 오기 형식 (csv, xml, xslx)을 갖습니다. 가져 오기 형식은 소스마다 다를 수 있습니다. 향후 새로운 가져 오기 형식이 추가 될 수 있습니다. 대상 객체 유형은 항상 동일합니다 (고객, 주소 등).

나는 제네릭 사용에 대해 생각하고 공장 패턴에 대해 읽었지만이 분야에서 꽤 큰 멍청한 사람이므로 조언을 환영합니다.

이 문제를 해결하기위한 적절한 디자인 패턴은 무엇입니까?


간단하게 유지하십시오.
— NoChance

답변:


11

당신은 멋진 개념으로 너무 빨리 가고 있었다. 제네릭-사례를 볼 때 사용하지만 걱정하지 마십시오. 팩토리 패턴-아직 너무 많은 유연성과 혼란이 추가되었습니다.

간단하게 유지하십시오. 기본 관행을 사용하십시오.

  1. XML에 대한 읽기, CSV에 대한 읽기를 수행하는 것의 공통점을 상상해보십시오. 다음 레코드, 다음 줄과 같은 것들. 새로운 형식이 추가 될 수 있으므로, 결정될 형식이 알려진 형식과 공통점이 있다고 생각하십시오. 이 공통성을 사용하고 '인터페이스'또는 모든 형식을 준수해야하는 계약을 정의하십시오. 공통점을 준수하지만 모두 특정 내부 규칙을 가질 수 있습니다.

  2. 데이터의 유효성을 검사하려면 새로운 또는 다른 유효성 검사기 코드 블록을 쉽게 연결할 수있는 방법을 제공하십시오. 다시 말하지만 특정 종류의 데이터 구성을 담당하는 각 유효성 검사기가 계약을 준수하는 인터페이스를 정의하십시오.

  3. 데이터 구성을 만들려면 제안 된 출력 개체를 무엇보다 설계 한 사람이 제한을받습니다. 데이터 객체의 다음 단계가 무엇인지 파악하고 최종 용도를 알고 최적화 할 수 있습니까? 예를 들어 객체가 대화 형 응용 프로그램에서 사용될 예정이라는 것을 알고 있다면 '개요'또는 객체 수 또는 다른 종류의 파생 정보를 제공하여 해당 앱 개발자에게 도움이 될 수 있습니다.

나는 이것들 대부분이 템플릿 패턴이나 전략 패턴이라고 말합니다. 전체 프로젝트는 어댑터 패턴입니다.


+1, 특히 첫 번째 단락의 경우 (그리고 마지막 단락에서 나와 같은 결론에 도달 한 것이 좋습니다).
— Doc Brown

또한 하나의 형식을 다른 형식으로 적용하기 위해 전체 프로젝트의 아키텍처를 염두에 두십시오. 다른 프로젝트에서 누군가가 그 일부만 사용할 수있는 상황을 상상할 수 있습니까? EG 아마도 새로운 데이터 유효성 검사기가 시장에 나와서 SQL 서버에서만 작동합니다. 이제 사용자 정의 XML을 읽고 SQL 서버에 넣고 나머지 단계를 건너 뛰기를 원합니다.
— Andyz Smith

이를 용이하게하기 위해, 조각들이 내부 계약을 고수 할뿐만 아니라 조각들 사이의 상호 작용을 정의하는 일련의 계약이 있어야합니다 .
— Andyz Smith

@AndyzSmith-코드에서 동일한 문제가 있습니다. 어댑터 패턴을 제외한 모든 코드에 대해 이해했습니다. 전체 프로젝트가 어댑터 패턴의 예라고 말했을 때이를 설명 할 수 있습니까?
— gansub

9

분명한 것은 전략 패턴 을 적용하는 것입니다 . 일반적인 기본 클래스를 가지고 ReadStrategy각각의 입력 형식과 같은 서브 클래스 XmlReadStrategy, CSVReadStrategy등이 당신이에서 인증 할 처리 및 출력 처리에서 독립적으로 가져 오기 처리를 변경할 수 있습니다.

세부 사항에 따라 가져 오기의 대부분을 일반으로 유지하고 입력 처리의 일부만 교환 할 수도 있습니다 (예 : 하나의 레코드 읽기). 이로 인해 Template Method pattern 이 나타날 수 있습니다 .


전략 패턴을 사용할 때 개체 (고객, 주소)를 원본에서 대상으로 변환하기위한 별도의 방법을 만들어야한다는 의미입니까? 내가하고 싶은 것은 각 객체를 읽고 변환하고 유효성을 검사 한 다음 목록을 나중에 데이터베이스에 저장할 수 있도록 목록에 넣는 것입니다.
— jao

@jao : 글쎄, 만약 당신이 나의 대답을 다시 읽으면, 나의 제안은 "ConvertStrategy"가 아니라 "ReadStrategy"를 만들라는 것을 알 수 있습니다. 따라서 객체 를 읽기 위한 다른 방법 (또는 특정 파일 형식에 따라 프로세스의 추가 부분) 만 작성하면됩니다 .
— Doc Brown

7

향후 확장해야 할 가져 오기 유틸리티에 적합한 패턴은 MEF를 사용하는 것입니다. 게으른 목록에서 필요한 변환기를 즉시로드하여 메모리 사용을 낮게 유지하고 속성으로 장식 된 MEF 가져 오기를 작성할 수 있습니다. 수행하려는 가져 오기에 적합한 변환기를 선택하고 다른 가져 오기 클래스를 쉽게 분리 할 수있는 방법을 제공합니다.

각 MEF 파트는 가져 오기 파일의 행을 출력 데이터로 변환하거나 기본 기능으로 기본 클래스를 대체하는 일부 표준 메소드를 사용하여 가져 오기 인터페이스를 충족하도록 빌드 할 수 있습니다.

MEF는 플러그인 아키텍처를 만들기위한 프레임 워크입니다. Outlook과 Visual Studio의 구축 방식은 VS의 모든 확장 기능이 MEF 파트입니다.

MEF (Managed Extensability Framework) 앱을 빌드하려면 System.ComponentModel.Composition

변환기가 수행 할 작업을 지정하기위한 인터페이스 정의

public interface IImportConverter
{
    int UserId { set; }        
    bool Validate(byte[] fileData, string fileName, ImportType importType);
    ImportResult ImportData(byte[] fileData, string fileName, ImportType importType);
}

가져 오려는 모든 파일 형식에 사용할 수 있습니다.

클래스가 "내보내기"대상을 정의하는 속성을 새 클래스에 추가

[Export(typeof(IImportConverter))]
[MyImport(ImportType.Address, ImportFileType.CSV, "4eca4a5f-74e0")]
public class ImportCSVFormat1 : ImportCSV, IImportConverter
{
 ...interface methods...
}

이것은 CSV 파일 (특정 형식 : Format1)을 가져올 클래스를 정의하고 MEF 내보내기 속성 메타 데이터를 설정하는 사용자 정의 속성을 갖습니다. 가져 오려는 각 형식 또는 파일 형식에 대해이 작업을 반복하십시오. 다음과 같은 클래스로 사용자 정의 속성을 설정할 수 있습니다.

[MetadataAttribute]
[AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
public class ImportAttribute : ExportAttribute
{
    public ImportAttribute(ImportType importType, ImportFileType fileType, string customerUID)
        : base(typeof(IImportConverter))
    {
        ImportType = importType;
        FileType = fileType;
        CustomerUID = customerUID;
    }

    public ImportType ImportType { get; set; }
    public ImportFileType FileType { get; set; }
    public string CustomerUID { get; set; }
}

실제로 MEF 변환기를 사용하려면 변환 코드가 실행될 때 생성 한 MEF 부품을 가져와야합니다.

[ImportMany(AllowRecomposition = true)]
protected internal Lazy<IImportConverter, IImportMetadata>[] converters { get; set; }
AggregateCatalog catalog = new AggregateCatalog();

catalog 폴더에서 부품을 수집하며 기본값은 앱 위치입니다.

converters 가져온 MEF 부품의 게으른 목록입니다.

그런 다음 어떤 종류의 파일을 변환 하려는지 알고 ( importFileType및 importType) 가져온 부품 목록에서 변환기를 가져옵니다.converters

var tmpConverter = (from x in converters
                    where x.Metadata.FileType == importFileType
                    && x.Metadata.ImportType == importType 
                    && (x.Metadata.CustomerUID == import.ImportDataCustomer.CustomerUID)
                    select x).OrderByDescending(x => x.Metadata.CustomerUID).FirstOrDefault();

if (tmpConverter != null)
{
     var converter = (IImportConverter)tmpConverter.Value;
     result = converter.ImportData(import.ImportDataFile, import.ImportDataFileName, importType);
....
}

에 대한 호출 converter.ImportData은 가져온 클래스에서 코드를 사용합니다.

많은 코드처럼 보일 수 있으며 머리를 돌리는 데 시간이 걸릴 수 있지만 새로운 변환기 유형을 추가 할 때 매우 유연하며 런타임 중에 새 유형을 추가 할 수도 있습니다.


전에 MEF에 대해 들어 본 적이 없습니다. 무엇입니까?
— jao

2
자세한 설명은 @jao check 링크 를 참조하십시오 . 내 답변에 MEF 자료의 예를 추가했습니다.
— Matt

1
이것은 MEF를 시작하는 훌륭한 방법입니다. +1
— paqogomez

MEF는 디자인 패턴이 아닌 기술입니다. -1기본 아이디어가 여전히 합리적이며 IImportConverter인터페이스가 지배하는 전략 패턴에 의존하기 때문에 나에게는 아닙니다 .
— GETah

0

이 문제를 해결하기위한 적절한 디자인 패턴은 무엇입니까?

C # 관용구에는 내장 직렬화 프레임 워크를 사용하여이를 수행합니다. 메타 데이터를 사용하여 개체에 주석을 달고 해당 주석을 사용하여 데이터를 추출하여 올바른 양식에 넣거나 그 반대의 다른 직렬 변환기를 인스턴스화합니다.

Xml, JSON 및 이진 형식이 가장 일반적이지만 다른 패키지가 이미 멋진 패키지 형식으로 존재하더라도 놀라지 않을 것입니다.


글쎄, 이것은 당신이 당신 자신의 파일 형식을 자유롭게 사용할 수 있다면 잘 작동하지만 XSLX와 같은 복잡하고 사전 정의 된 형식에 대해서는이 접근법이 실패 할 것입니다. 이는 압축 된 XML 형식의 MS Excel 파일을 의미합니다.
— Doc Brown

Excel 파일의 줄을 개체에 매핑 할 수 있지만 해당 방법을 복사하여 XML 및 CSV 리더에 적용해야합니다. 코드를 최대한 깨끗하게 유지하고 싶습니다.
— jao

@docBrown-어떻게? 개념적으로 Excel에서 개체를 일련의 셀로 변환하는 것은 XML 문서로 변환하는 것과 실제로 다르지 않습니다.
— Telastyn

@ Telastyn : .NET 프레임 워크 의 내장 직렬화 프레임 워크 를 사용 하여 XLSX 형식을 읽을 수 있다고 말 합니까? 이것이 사실이라면 Open XML SDK 또는 NPOI와 같은 라이브러리는 더 이상 사용되지 않습니다.
— Doc Brown

@docbrown : 사과합니다. 당신은 맞습니다. 저는 공통 시리얼 라이저 기본 클래스가 없다는 것을 잊고 있습니다. 왜냐하면 제가 작업하는 모든 코드베이스에서 처음으로 수행되는 것 중 하나입니다.
— Telastyn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.