.NET kitaplığınızı COM sınırlamaları göz önünde bulundurularak yazmak veya .NET kitaplığınızı Interop'tan ayırmak daha iyi mi?


9

Bu ilginç makaleye rastladım: CodeProject'teki COM Birlikte Çalışabilirliğini Sevmeye Nasıl Geldim, ki beni düşündürdü ...

Yazar, .NET kitaplıklarında COM-ities istemediklerini çünkü .NET kitaplıklarının güzelliğinden uzak durduklarını iddia ediyor. Bunun yerine, .NET kitaplıklarını COM'a gösteren ayrı bir Interop kitaplığı yazmayı tercih ederler. Bu Interop kütüphanesi, COM'un Parametreler, Aşırı Yüklü Yöntemler, Jenerikler, Kalıtım, Statik Yöntemler vb.

Ve bunun çok yeni olduğunu düşünürken, sadece projeye uygun değil mi?

  • Şimdi .NET kitaplığınızı VE bir Interop kitaplığını birim test etmeniz gerekir.
  • Şimdi, güzel .NET kitaplığınızın etrafında nasıl çalışacağınızı ve COM'a nasıl maruz bırakacağınızı anlamaya zaman harcamanız gerekiyor.
  • Sınıf sayınızı etkili bir şekilde iki veya üç katına çıkarmanız gerekir.

COM ve COM olmayanları desteklemek için kütüphanenize ihtiyacınız olup olmadığını kesinlikle anlayabiliyorum. Ancak, sadece COM kullanmayı düşünüyorsanız, bu tür bir tasarım görmediğim herhangi bir fayda getiriyor mu? Sadece C # dilinin avantajlarını mı elde ediyorsunuz?

Yoksa size bir sarıcı sağlayarak kitaplığınızı sürümlendirmeyi kolaylaştırıyor mu? COM kullanımını gerektirmeden Birim Testlerinizin daha hızlı çalışmasını sağlıyor mu?


2
Yani, gerçek kodu daha iyi / temiz hale getirmek için yararlı araçlar kullanabilmenin yanı sıra? Ve bu (muhtemelen eski) COM şeyler için açık bir geçiş yolu sağlamak?
telastin

3
Bu, tüm bir ad alanı üzerinde büyük bir cephe deseni gibidir. .NET özelliklerini kullanmak istiyorsanız gerçekten böyle organize etmenin akıllıca olduğunu düşünüyorum ama gerçekten OLE Otomasyonu gerekiyor. COM paketleyicileriniz temel olarak modern (değişmez? Genel?) Deyimleri parametresiz yapıcılar, yoğun şekilde değiştirilebilir nesneler ve genel listeleriniz için SAFEARRAY'lerle eski COM nesnelerine dönüştürmek olacaktır. Diğer .NET bileşenlerini destekliyorsanız veya yeni stillere tamamen aşıksanız, bu mantıklı olacaktır. SADECE COM'u destekliyorsanız, neden her şeyi VB6'ya (32 bit) yazmıyorsunuz ve sadece bir deyim tutmuyorsunuz?
Mike

3
@MasonWheeler: 6 aydan eski tüm yazılımlar "miras" ile aynı şekilde kaldırıldı, doğru mu?
whatsisname

2
@MasonWheeler COM, ne kadar insanın (Microsoft içindeki bazı gruplar da dahil olmak üzere) dilediğine bakılmaksızın amortismana tabi tutulamaz, çünkü işlem dışı işlemleri kontrol etmek için hala en iyi seçimdir.
Mike

2
@Mike, aslında C # .NET bir VB6 projesi taşıma bakıyorum. Kullandığımız kullanıcıya yönelik API'ler çok basittir, ancak sahne arkasındaki kod olduğu gibi sürdürülemez. C # .NET kütüphanesinin çoğunu uygulamak ve çeşitli sınıflarla etkileşim basit API sağlayan bir Interop Cephe sağlamak umuyoruz.
robodude666

Yanıtlar:


7

Ancak, sadece COM kullanmayı düşünüyorsanız, bu tür bir tasarım görmediğim herhangi bir fayda getiriyor mu?

Sorunuzun Bu snippet'idir burada tasarım kararın en önemli parçası ve cevap (her zaman olduğu gibi) 'dir duruma göre değişir .

Kütüphaneyi sadece COM Interop ile kullanmak istiyorsanız, tüm sistemi bu düşünceyle tasarlamalısınız. Hat sayısını üçe katlamak için hiçbir neden yoktur. Sistemde ne kadar çok LoC olursa, o kadar fazla kusur olacaktır. Bu nedenle, sisteminizi yalnızca COM uyumlu işlevleri kullanacak şekilde tasarlamalısınız.

Ancak , .Net kitaplığı kullanımını COM ile kısıtlamak için iyi bir neden düşünemiyorum. Neden diğer .Net kodlarında derleme kullanmak istemezsiniz? Kendinizi bu şekilde sınırlamak çok mantıklı değil.

Bununla ilgili biraz deneyimim var, bu yüzden onu nasıl ele aldığımı paylaşacağım. Kesinlikle ideal değil. Bazı takaslar yaptım. Yalnızca yeni .Net deyimleriyle uyumlu olmayan COM sınıfları (gerçekten arayüzler) için bir cephe kullanıyorum, aksi takdirde .Net arayüzünü doğrudan COM'a maruz bırakıyorum. Bu temel olarak jenerik ilaç kullanan herhangi bir arayüz için bir cephe kullandığım anlamına gelir. Genel olarak karşılaştığım tek şey jenerikler sadece uyumsuz. Ne yazık ki, bu IEnumerable<T>oldukça yaygın olan ve geri dönen her şey için bir cephe anlamına gelir .

Bununla birlikte, bu neredeyse göründüğü kadar kötü değil, çünkü cephe sınıfınız .Net sınıfınızdan miras alır ve belirli bir Interop arabirimi uygular. Böyle bir şey.

namespace Company.Product.Feature
{
    public class MyClass : INetInterface 
    {
        // lots of code
    }
}

namespace Company.Product.Interop
{
    public class MyClass : Feature.MyClass, IComInterface
    {
        // over ride only the  incompatible properties/methods
    }
}

Bu, yinelenen kodunuzu mutlak minimumda tutar ve COM arayüzünüzü "istem dışı" değişikliklerden korur. Çekirdek sınıfınız / arayüzünüz değiştikçe, adaptör sınıfınız daha fazla yönteme ihtiyaç duyar (veya arayüzü kırıp ana sürüm numarasını çarptırır). Öte yandan, tüm Interop kodunuz Interopad alanında depolanmaz , bu da kafa karıştırıcı bir dosya organizasyonuna yol açabilir. Dediğim gibi, bu bir değiş tokuş.

Bunun tam bir örneği için, depomun SourceControl ve Interop klasörlerine göz atabilirsiniz . ISourceControlProviderve GitProviderözellikle ilgi çekecek.


@RubberDuck yanıtı için teşekkürler! Birkaç gün önce RubberDuck projesiyle karşılaştım; kodu okumak çok ilginçti. IEnumerableVBA'ya geçebiliyor musunuz? Ayrıca, Rubberduck.Interop.GitProviderCOM bunları desteklemiyorsa neden parametreli kurucuları tanımladınız?
robodude666

Evet, bir IEnumerableCOM üzerinden geçebilirsiniz , ancak daha eski, genel olmayan sürüm olmalıdır. Inşaatçılar gelince, bir göz atın SourceControlClassFactory. Temel olarak, ctor için parametrelere ihtiyaç duymayan bir sınıf örneğini başlatarak ve API'nizin sınıflarının yeni örneklerine erişim elde etmek için kullanabilirsiniz.
RubberDuck

Ben ComVisible(true)sınıflar / arayüzler içinde COM desteklemiyor tanımlanan herhangi bir şey sadece "göz ardı" olduğunu tahmin ediyorum ? Birden fazla ad alanında tanımlanmış aynı ada sahip bir sınıfınız ProgIdvarsa, bunlardan birden fazlasını ortaya çıkarmak istiyorsanız benzersiz bir özellik sağlamanız gerektiğini de tahmin ediyorum.
robodude666

Evet. Bu doğru ve staticyöntemler göz ardı ediliyor. VB6'nın eşdeğeri olup olmadığını görmeye çalışıyorum VB_PredeclaredId. Varsayılan bir örnek oluşturmak mümkün olabileceğini düşünüyorum .
RubberDuck

7

.NET kütüphanelerinin güzelliğinden uzaklaşıyor

Bu yazarın yüzüne uyanma tokatına ihtiyacı var. Herhangi bir profesyonel proje için amaç, insanların kullanmak istedikleri çalışan yazılımlar yapmaktır. Bundan sonra güzellikle ilgili her türlü yanlış yönlendirilmiş idealler gelir. Tek sebepleri bu ise, yazar tüm güvenilirliğini kaybetti.

Sınıflarınızı com-visible olarak işaretleyebilmeniz ve COM kodunuzla COM aracılığıyla konuşabilmeniz çok faydalıdır. Güzellik için üretkenliğe büyük fayda sağlamanın çılgınca olması.

Ancak, şeylerin COM ile çalışmasını sağlamak bazı değiş tokuşlar gerektirir, arg-no yapıcı gerektirmez bunlardan biri ve bahsettiğiniz diğer şeyler. Bunlar zaten kullanmadığınız özelliklerse veya bunları kullanmamanıza zarar vermezse, COM ve com olmayanlar için aynı sınıfı kullanarak kaydedilecek çok iş var.

Öte yandan, COM istemcileriniz önemli ölçüde farklı bir arabirim beklerse, .NET sınıflarınızda başa çıkmak için kötü olan bağımlılıklar veya diğer sınırlamalar varsa veya .NET sınıflarınızı önemli ölçüde değiştirmeyi ve COM'u geriye doğru korumayı beklediğinizden daha sonra bu boşluğu kapatmak için bir Interop sınıfı oluşturun.

Ama "güzellik" hakkında düşünmeyin. COM ile COM'u açığa çıkarabilmeniz, işinizi kurtaracak anlamına gelir. Kendiniz için daha fazla iş yaratmayın.


+1. Kara kutudaki siyah düğmelerin güzelliğini sevmeme rağmen pratiklik çok daha önemlidir.
gbjbaanb

Aslında, "güzellik" terimini bu tartışmaya sokan kişinin bir uyanma tokatına ihtiyacı olabilir ve bu diğer makalenin yazarı değildi.
Doc Brown

2
Sadece bir yan not, mevcut kurucularınız argüman gerektiriyorsa, mevcut arayüz / API'yi yeniden tasarlamak yerine COM bileşenleriniz için bir sınıf fabrikası sağlamak en iyisidir.
RubberDuck

1
Fabrikanızı "GlobalMultiUse" sınıfı olarak tanıtmak mümkün mü? Yani Set oObject = MyCOMInterop.NewMyClass()yeni bir Fabrika nesnesini ilk olarak başlatmak zorunda kalmadan yapabilirsiniz ?
robodude666

Bu lanet iyi bir soru @ robodude666. Şimdi bahsettiğinize göre, umarım öyle olur.
RubberDuck

3

Adil olmak gerekirse, bu makalenin orijinal yazarı makalesinde hiçbir yerde "güzellik" kelimesini kullanmadı, bu makaleyi okumak için zaman almayanlar için önyargılı bir izlenim bırakabilirdiniz. kendilerini.

Bu makaleyi anladığım kadarıyla, .NET kütüphanesi zaten var ve COM düşünülmeden yazılmıştır - muhtemelen kütüphanenin oluşturulduğu zamanda COM'u desteklemeye gerek yoktu.

Daha sonra, COM'u desteklemek için ek gereklilik tanıtıldı. Böyle bir durumla karşı karşıya kaldığınızda iki seçeneğiniz vardır:

  • orijinal lib'i COM birlikte çalışabilirliği ile uyumlu hale getirmek için yeniden tasarlayın (bazı şeyleri kırma riskiyle)

  • orijinal çalışma kitaplığını çoğunlukla olduğu gibi bırakın ve bunun yerine "sarmalayıcı" (veya "bağdaştırıcı") işleviyle ayrı bir montaj oluşturun

Sarmalayıcılar veya adaptörler oluşturmak iyi bilinen bir tasarım modelidir (veya bu durumda daha mimari bir modeldir) ve artıları ve eksileri de iyi bilinir. Bunun bir argümanı daha iyi “endişelerin ayrılması” dır ve bunun güzellikle hiçbir ilgisi yoktur.

Endişeleriniz için

Şimdi .NET kitaplığınızı VE bir Interop kitaplığını birim test etmeniz gerekir.

COM arabiriminizi yeniden tasarlayarak varolan .NET kitaplığınıza tanıttığınızda, bu arabirimi de sınamanız gerekir. Elle yazılmış bir adaptörün tanıtımı, elbette arayüzün çalıştığı bazı ek testlere ihtiyaç duyabilir, ancak lib'in temel iş işlevselliğinin tüm birim testlerini kopyalamaya gerek yoktur. Unutmayın, sadece lib için başka bir arayüz.

Şimdi, güzel .NET kitaplığınızın etrafında nasıl çalışacağınızı ve COM'a nasıl maruz bırakacağınızı anlamaya zaman harcamanız gerekiyor.

Orijinal kütüphaneyi yeniden tasarlamanız gerektiğinde bunu da anlamanız gerekir ve sanırım çok daha fazla iş olacak.

Sınıf sayınızı etkili bir şekilde iki veya üç katına çıkarmanız gerekir.

Yalnızca orijinal COM arabiriminin sınıfların az bir kısmı olması gereken genel COM arabirimi aracılığıyla maruz kalan sınıflar için.

Bahsettiğiniz farklı bir durum için, COM'u en başından itibaren birinci sınıf bir vatandaş olarak desteklemeniz gerektiğini zaten bildiğinizde, doğru olduğunu düşünüyorum: biri ayrı bir adaptör lib ekleme ve Doğrudan COM desteği ile .NET lib.


(+1) Ancak, "... az sayıda olması gereken ... orijinal kütüphane" sadece bazen doğrudur. Bir sınıfın herkesin görebildiği tek bir amaca eşit olduğu ve sınıfların ilginç işlevsellik sağlamak için oluşturduğu "sınıf kitaplığı stili" nde tasarlanan birçok proje türü vardır. Bu durumda, .NET sınıfı sayısı ile COM birlikte çalışma sınıfı sayısı arasında bire bir eşleme olabilir.
rwong
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.