2015-02-25 16 views
5

PDFView4Net kullanarak PDF formları oluşturmak için bir proje üzerinde çalışıyorum. Kütüphane genel olarak iyi olsa da, form oluşturucu ilkeldir ve form alanları ile çalışırken (metin kutuları, onay kutuları, vb.) Temel özellikleri (kopyalama/yapıştırma, hizalama, biçimlendirme vb.) Içermez.Karmaşık Üçüncü Şahıs Nesneleri/Sınıfları'nın Derin Kopyası

sorun: Ben saha nesneler için işlevsellik uzanan edilmiş ve kopyala/yapıştır üzerinde takıldı alma. Bunu yapmak için, orijinaline hiçbir atıfta bulunmadan nesnenin derin bir kopyasına ihtiyacım var. Satıcıya e-posta göndererek, bu nesnelerin kopyalanması için önerilen metotları hakkında bilgi talep ettim, cevap verdiler. Her bir mülkün el ile bir kopyasını el ile yapmalıyım. , masanın üzerinde. Bunlar, özellikler olarak çoklu gömülü sınıfların yanı sıra UI öğelerine sahip büyük sınıflardır.

soru: Kaynak sınıflara erişimi veya değişiklik gerektirmeyen seri gerektirmeyen karmaşık nesneler için derin bir kopyasını yapmak orada herhangi iyi yöntemler var mıdır ve gerektirmez varsayılan kurucu?

gözden denedim ne /: Ben bir nesnenin derin bir kopyasını yapmak için çeşitli yollar araştırılmış ve birer birer atılır var:

  • Elle, Özenli Mülk tarafından Mülkiyet: Ben bunu 7 alan nesnesi (PDFTextBoxField) ile denedi, ama aynı zamanda farklı sınıf türleri olan çokluk özellikleriyle çabucak elden çıktı. Sonunda, hala, amaçlandığı gibi derin bir kopya yerine sığ bir kopyanın oluşturulduğu orijinal nesneye referansları devam ettirdim.
  • Serileştirme: Sınıflar Seri hale getirilebilir olarak işaretlenmez ve satıcı bunu değiştirmez. Onlara sordum ve hayır dediler. ICSIP: Satıcı tarafından uygulanması gerekir.
  • AutoMapper: Bu, bir veya daha fazla nesne türündeki veriyi başka bir nesne türüne kopyalamak için görünüyor. Çalıştığım nesneler aynı tipte. En iyi çözüm ise bunu kullanmaya karşı değilim.
  • Emit Mapper: Bu proje terk edilmiş gibi görünüyor.
  • MemberwiseClone: ​​Aradığım derin kopya değil, sığ bir kopya var, ancak bu soruya özel olarak derin bir kopyasını istediğinde, bu bir başka yazılarda önerilir.
  • Value Enjecter: CodePlex üzerinde ValueInjecter'dan FastDeepCloneInjection uyguladım, ancak en çok enjekte edilmesi gereken sınıfların çoğunun, kopya için yeni bir örnek oluştururken gereken 0 parametre yapıcısı yok. ValueInjecter, belirli özelliklerin atlanmasına izin vermez veya yalnızca varsayılan kurucu içermeyen öğeleri atlar ve bunları null (varsayılan) olarak bırakır. Bunu ilk sınıfla hemen yaşadım. Bu sorunu çözmeye çalışmak için, orijinalden miras alınmış bir sarıcı sınıf oluşturdum ve orijinali sargıya dönüştürdüm (ve tersi de tersi), ama bunun iyi bir çözüm olduğunu düşünmüyorum.

Düzenleme: Gerçekten bu soruyu hissetmiyorum kopyası. Yinelenen/orijinal olarak işaretlenen yazı da dahil olmak üzere bir çözüm için kapsamlı arama yaptım ve tatmin edici bir çözünürlük bulamadı. Belirtildiği gibi, kopyalamam gereken sınıfları değiştirmek için erişimim yok.Bu DataContractSerializer, BinaryFormatter ve diğer herhangi bir serileştirme türünü indirir. Bu, Activator.CreateInstance kullanarak gördüğüm yansıma örneklerini de, kopyalamak için ihtiyacım olan sınıfların yaklaşık% 95'inin 0 bağımsız değişkene sahip olmadığı bir kurucuya sahip olmadığına benziyor. Bu ValueInjecter kullanarak rastladığım aynı sorundur. Bu da ICONeable kullanarak indirimler.

+1

nasıl güzel [yansıma ve özyineleme] hakkında (http: // stackoverflow .com/a/13199808/2589202)? – paqogomez

+0

Bir nesneyi herhangi bir el ile seri hale getirilmiş serileştirme (önerilen yansıma ve yineleme) ile klonlamak için, * FormatterServices.GetUninitializedObject (type) 'aracılığıyla * constructor çağrısı olmadan boş bir örnek oluşturarak * başlamanız gerekir. –

+0

Belki bir şey gibi: https: //code.msdn.microsoft.com/CSDeepCloneObject-8a53311e veya http://www.codeproject.com/Articles/38270/Deep-copy-of-objects-in-C veya http://thomashapp.com/node/106 –

cevap

2

Bunun için AutoMapper kullanırım. Aşağıdaki sınıf tanımını göz önünde bulundurun: Bu durumda, derin klon kurulum AutoMapper gerekli gibi

public class Parent 
{ 
    public string Field1 { get; set; } 
    public Level1 Level1 { get; set; } 
    public static Parent GetInstance() 
    { 
     return new Parent() { Field1 = "1", Level1 = new Level1 { Field2 = "2", Level2 = new Level2() { Field3 = "3"}}}; 
    } 
    private Parent() {    } 
} 

public class Level1 
{ 
    public string Field2 { get; set; } 
    public Level2 Level2 { get; set; } 
} 

public class Level2 
{ 
    public string Field3 { get; set; } 
} 

(özel ctor dikkat edin):

[TestMethod] 
public void DeepCloneParent() 
{ 
    Mapper.CreateMap<Parent, Parent>(); 
    Mapper.CreateMap<Level1, Level1>(); 
    Mapper.CreateMap<Level2, Level2>(); 
    var parent = Parent.GetInstance(); 

    var copy = Mapper.Map<Parent, Parent>(parent); 

    Assert.IsFalse(copy == parent);//diff object 
    Assert.IsFalse(copy.Level1 == parent.Level1);//diff object 
    Assert.IsFalse(copy.Level1.Level2 == parent.Level1.Level2);//diff object 
    Assert.AreEqual("1", copy.Field1); 
    Assert.AreEqual("2", copy.Level1.Field2); 
    Assert.AreEqual("3", copy.Level1.Level2.Field3); 
} 
+0

klonlanan sınıflara erişimi olmadığı sürece bağlantı önerisi için teşekkürler. AutoMapper kullanarak başarıyla kopyalamak için 7 alandan ilkini alabiliyordum. Yine de bunun en iyi çözüm olduğuna emin değilim. PDFView4Net sınıf kitaplığı 266 sınıf içerir. Sadece bir tanesi hatasız kopyalamak için 400'ün üzerinde kod aldı. Yine de, sanırım hepsini el ile yapmaktan daha iyidir. – mslissap

+0

@mslissap neden bu kadar çok çizgi? (ilk kopyaya kaç tane sınıf katıldı?) 1. kopya için – wal

+0

116 sınıfları. Satıcı çok sayıda "mini" sınıfını kullanmaktadır (mülkiyet C, B'den miras, A'dan miras mi, mirastan miras). Tek bir mülk için gereken 4-5 sınıf olabilir. Bu, kopyalamak için ihtiyaç duyduğum 7 nesnenin en basitiydi, ancak diğerleri miras almak için aynı "taban" sınıflarının çoğunu kullanıyorlar. Birçoğu için hiçbir parametresiz yapıcı (bunları varsayılan olarak) olmadığı için CreateMap.ConstructUsing için bir ResolutionContext oluşturmak zorunda kaldım, daha sonra gerçek değeri kaynağından almak ve hedefe ulaşmak için bir AfterMap eylemi oluşturun. – mslissap

İlgili konular