Çeşitli kaynak türlerine ve çeşitli hedef türlerine veri içe aktarmak için Tasarım Deseni


14

Tasarım ve aşağıdakileri işleyebilir (C #) bir ithalat komut dosyası oluşturmak zorunda:

  • çeşitli kaynaklardan (XML, XSLX, CSV) veri okuma
  • verileri doğrula
  • verileri çeşitli nesne türlerine (müşteri, adres) yazın

Veriler birkaç kaynaktan gelecektir, ancak bir kaynağın her zaman bir içe aktarma biçimi olacaktır (csv, xml, xslx). İçe aktarma biçimleri kaynaktan kaynağa değişebilir. Gelecekte yeni içe aktarma biçimleri eklenebilir. Hedef nesne türleri her zaman aynıdır (müşteri, adresler ve daha fazlası).

Jenerik ilaç kullanmayı düşünüyorum ve fabrika modeli hakkında bir şeyler okudum ama bu alanda oldukça büyük bir çaylağım, bu yüzden herhangi bir tavsiye hoş geldiniz.

Bu sorunu çözmek için uygun tasarım deseni nedir?


Basit tutun.
NoChance

Yanıtlar:


11

Çok yakında süslü konseptlerle denize gidiyorsunuz. Jenerikler - bir vaka gördüğünüzde bunları kullanın, ancak aksi halde endişelenmeyin. Fabrika düzeni - bunun için çok fazla esneklik (ve karışıklık ekledi).

Basit tutun. Temel uygulamaları kullanın.

  1. XML için bir okuma yapmak, CSV için bir okuma yapmak gibi genel şeyleri hayal etmeye çalışın. Sonraki kayıt, sonraki satır gibi şeyler. Yeni formatlar eklenebileceğinden, belirlenecek formatın bilinen formatlarla olan ortaklığını hayal etmeye çalışın. Bu ortak özelliği kullanın ve tüm biçimlerin uyması gereken bir 'arayüz' veya sözleşme tanımlayın. Ortak zemine bağlı olsalar da, hepsinin kendi iç kuralları olabilir.

  2. Verileri doğrulamak için yeni veya farklı doğrulayıcı kod bloklarını kolayca takmanın bir yolunu sağlamaya çalışın. Bu nedenle, belirli bir veri yapısından sorumlu her doğrulayıcının bir sözleşmeye bağlı kaldığı bir arabirim tanımlamaya çalışın.

  3. Veri yapılarını oluşturmak için muhtemelen önerilen çıktı nesnelerini her şeyden daha fazla tasarlayanlar tarafından kısıtlanacaksınız. Veri nesneleri için bir sonraki adımın ne olduğunu anlamaya çalışın ve son kullanımı bilerek yapabileceğiniz herhangi bir optimizasyon var mı? Örneğin, nesnelerin etkileşimli bir uygulamada kullanılacağını biliyorsanız, nesnelerin ya da diğer türetilmiş bilgilerin 'özetlerini' ya da sayılarını sağlayarak söz konusu uygulamanın geliştiricisine yardımcı olabilirsiniz.

Bunların çoğunun Şablon kalıpları veya Strateji kalıpları olduğunu söyleyebilirim. Tüm proje bir Adaptör modeli olacaktır.


+1, özellikle ilk paragraf için (ve son paragrafta benimle aynı sonuca vardığınızı görmek güzel).
Doc Brown

Ayrıca, bir formatı diğerine uyarlamak için tüm projenin mimarisini unutmayın. Birisinin başka bir projede bunun sadece bir kısmını kullanabileceği bir durum hayal edebiliyor musunuz? EG Belki yeni bir veri doğrulayıcı piyasaya çıkıyor ve sadece SQL sunucusuyla çalışıyor. Yani şimdi sadece özel XML okumak ve SQL sunucusuna koymak, geri kalan adımları atlamak istiyorum.
Andyz Smith

Bunu kolaylaştırmak için, sadece parçaların bağlı oldukları iç sözleşmeleri olmasa da, parçalar arasındaki etkileşimi tanımlayan bir dizi sözleşme olmalıdır .
Andyz Smith

@AndyzSmith - Kodumda aynı sorun var. Adaptör modeli dışında kodunuzla ilgili her şeyi anladım. Tüm projenin Adaptör modelinin bir örneği olduğunu söylediğinizde bunu gösterebilir misiniz?
gansub

9

Açık olan, Strateji modelini uygulamaktır . Genel taban sınıf var ReadStrategyve her giriş biçimi için böyle bir alt sınıf XmlReadStrategy, CSVReadStrategyvb Bu doğrulaması ise işleme ve çıkış işlemeden bağımsız ithalat işleme değiştirmeye izin verecektir.

Detaylara bağlı olarak, içe aktarma işleminin çoğu kısmını genel tutmak ve girdi işlemenin yalnızca bir kısmını değiştirmek (örneğin, bir kaydın okunması) mümkün olabilir. Bu sizi Şablon Yöntemi desenine yönlendirebilir .


Bu, strateji modelini kullanırken, nesneleri (müşteri, adres) kaynaktan hedefe dönüştürmek için ayrı yöntemler oluşturmak zorunda olduğum anlamına mı geliyor? Ne yapmak istiyorum okumak, dönüştürmek ve her nesne doğrulamak ve liste daha sonra veritabanına kaydedilebilir böylece bir listeye koymaktır.
jao

@jao: Cevabımı tekrar okursanız, önerimin "ConvertStrategy" değil "ReadStrategy" oluşturmak olduğunu görürsünüz. Bu nedenle, yalnızca nesneleri okumak için farklı yöntemler yazmanız gerekir (veya işleminizin ek kısmı, belirli dosya biçimi için ayrıdır).
Doc Brown

7

İleride genişletmeniz gerekebilecek bir içe aktarma yardımcı programı için uygun bir desen MEF kullanmak olacaktır - tembel bir listeden anında ihtiyacınız olan dönüştürücüyü yükleyerek bellek kullanımını düşük tutabilir, özelliklerle süslenmiş MEF ithalatları oluşturabilirsiniz gerçekleştirmeye çalıştığınız içe aktarma için doğru dönüştürücüyü seçmenize yardımcı olur ve farklı içe aktarma sınıflarını ayırmanın kolay bir yolunu sunar.

Her MEF parçası, içe aktarma dosyasının bir satırını çıktı verilerinize dönüştüren veya temel işlevselliğe sahip bir temel sınıfı geçersiz kılan bazı standart yöntemlerle bir içe aktarma arabirimini karşılamak için oluşturulabilir.

MEF bir eklenti mimarisi oluşturmak için bir çerçevedir - görünüm ve Visual Studio'nun nasıl oluşturulduğu, VS'deki tüm bu güzel uzantılar MEF parçalarıdır.

Bir MEF (Yönetilebilir Genişletilebilirlik Çerçevesi) uygulaması oluşturmak için, System.ComponentModel.Composition

Dönüştürücünün ne yapacağını belirlemek için arayüzleri tanımlayın

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

Bu, içe aktarmak istediğiniz tüm dosya türleri için kullanılabilir.

Yeni bir sınıfa, sınıfın neyi "Dışa aktaracağını" belirten özellikler ekleyin

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

Bu, CSV dosyalarını (belirli bir biçimde: Format1) içe aktaracak ve MEF Export Attribute Meta Verilerini ayarlayan özel niteliklere sahip bir sınıf tanımlar. Almak istediğiniz her biçim veya dosya türü için bunu tekrar edersiniz. Aşağıdaki gibi bir sınıfla özel öznitelikler ayarlayabilirsiniz:

[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; }
}

Aslında MEF dönüştürücülerini kullanmak için, dönüştürme kodunuz çalıştırıldığında oluşturduğunuz MEF parçalarını içe aktarmanız gerekir:

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

catalog parçaları bir klasörden toplar, varsayılan uygulama konumudur.

converters içe aktarılan MEF parçalarının tembel bir listesidir

Ardından, ne tür bir dosyayı dönüştürmek istediğinizi bildiğinizde ( importFileTypeve importType) içe aktarılan parçalar listesinden bir dönüştürücü alınconverters

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);
....
}

To call converter.ImportData, içe aktarılan sınıftaki kodu kullanır.

Çok fazla kod gibi görünebilir ve başınızın ne olup bittiğini görmek biraz zaman alabilir, ancak yeni dönüştürücü türleri eklemek söz konusu olduğunda son derece esnektir ve hatta çalışma zamanı sırasında yenilerini eklemenize izin verebilir.


Daha önce MEF'i duymadım. Bu ne?
jao

2
@jao tam açıklama için bağlantıyı kontrol edin . Cevabıma bazı MEF örnekleri ekledim.
Matt

1
Bu, MEF'e başlamak için mükemmel bir yoldur. +1
paqogomez

MEF bir tasarım deseni değil bir teknolojidir. Hayır -1, altta yatan fikir hala mantıklı ve IImportConverterarayüz tarafından yönetilen bir strateji modeline dayanıyor .
GETah

0

Bu sorunu çözmek için uygun tasarım deseni nedir?

C # deyimleri, bunu yapmak için yerleşik serileştirme çerçevesinin kullanılmasını içerir. Meta verilerle nesnelere açıklama ekledikten sonra verileri doğru forma sokmak için kopyalamak için bu ek açıklamaları kullanan farklı serileştiricileri başlatırsınız veya bunun tersini yaparsınız.

Xml, JSON ve ikili formlar en yaygın olanıdır, ancak başkaları tüketmeniz için zaten güzel bir paket halinde mevcutsa şaşırmam.


Kendi dosya biçiminizi kullanmakta özgürseniz bu iyi çalışır, ancak sanırım bu yaklaşım, XSLX gibi karmaşık, önceden tanımlanmış biçimler için başarısız olacaktır, bu da MS Excel dosyalarını sıkıştırılmış XML biçiminde anlamına gelir.
Doc Brown

Bir Excel dosyasının bir satırını bir nesneye eşleyebilirim, ancak bu yöntemi kopyalayıp XML ve CSV okuyucularına uyarlamam gerekir. Ve kodu olabildiğince temiz tutmak istiyorum ...
jao

@docBrown - nasıl? Kavramsal olarak, bir nesneyi Excel'de bir dizi hücreye dönüştürmek, bir xml belgesine dönüştürmekten gerçekten farklı değildir.
Telastyn

@Telastyn: XLSX biçimini okumak için .NET çerçevesinin yerleşik serileştirme çerçevesini kullanabileceğinizi mi söylüyorsunuz ? Bu doğruysa, Açık XML SDK veya NPOI gibi kütüphaneler eskiydi.
Doc Brown

@docbrown: özür dilerim, haklısın - ortak bir serileştirici taban sınıfı olmadığını unutmaya devam ediyorum, çünkü bu çalıştığım kod tabanlarında yapılan ilk şeylerden biri.
Telastyn
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.