Platforma bağımlı referanslarla Windows ve Mac için .Net kitaplığı oluşturmanın bir yolu var mı?


12

C # kullanarak masaüstü bilgisayarlar için (Windows ve Mac) çapraz platform uygulaması geliştirmeye çalışıyoruz. Uygulamaya platform bağımlı şeyler büyük miktarda içerir ve ekibimizin kurşun C # tüm bu kodu yazmak istiyor. Bunu yapmanın kolay yolu, C ++ 'da sarmalayıcılar yazmak ve sadece C # kodundaki kitaplıklara başvurmak ve C ++ kitaplıklarının platform öğeleriyle uğraşmasına izin vermektir ... ne yazık ki, öyle değil.

Mac için Visual Studio kullanarak bir kütüphane kurmaya çalışıyorum. Mevcut platformda yerel metin konuşma kütüphanesine erişim vermek için tek bir kütüphanede tek bir arayüz sağlayabilmeyi umuyorum - tercihen iki derleme yapmadan. Windows için C #'daki metin-konuşma kütüphanesi Mac'te mevcut değildir, bu yüzden kendimize bir köprü sağlamaktan başka alternatif bir seçeneğimiz yoktur.

Hangi işletim sistemi üzerinde çalıştığını belirlemek ve / veya yerel kütüphanelerin bir demet yüklemek ve sadece herhangi bir kütüphane yüklenecek kullanarak bir kütüphane yüklemek için işletim sistemi arama yapmak zorunda mutluyum.

Gerekirse, iki uygulama yazmama izin verecek tek bir projeye sahip olmak zorunda kalacak. Mac için Visual Studio'da kitaplık projesi oluşturmanın bir yolunu bulamadım , ancak bu bana izin veriyor. Birden fazla uygulamaya izin verecek tek proje türü, uygulamaların iOS veya Android için yapılmasını gerektiriyor gibi görünmektedir.


Hangi .NET çalışma zamanını kullanacaksınız?
Euphoric

2
Xamarin benzer bir şey yapar. Belki yapı yapılandırmalarıyla?
Ewan

2
Mac için Visual Studio'nun gerçekten görsel stüdyo olmadığını, onun sadece yeniden yapılandırılmış bir Xamarin stüdyosu olduğunu belirtmek gerekir. Belki de Xamarin belgelerinde bir şey var mı?
richzilla

3
En iyi yaklaşım farklı montajlar olacak ... Biri arayüzler ve ortak kod ve bir tanesi hedef platform için. Bununla birlikte, uygulamaları değiştirmek için #if ifadelerini çoklu hedefleyebilir ve kullanabilirsiniz. Dezavantajı, etkinleştirilmemiş olan herhangi bir şeyin değerlendirilmemesidir, böylece kolayca eski olabilir.
Berin Loritsch

Platforma bağımlı referanslar derken, yerel kod veya tüm C # kodlarından mı bahsediyorsunuz?
Berin Loritsch

Yanıtlar:


4

Güzel bir sorunuz var. Muhtemelen çözümünüzle bazı değiş tokuşlar vardır. Nihai cevap gerçekten platforma bağlı ne demek istediğinize bağlıdır. Örneğin, harici uygulamaları başlatmak için bir işlem başlatıyorsanız ve sadece bir uygulama ile diğeri arasında geçiş yapıyorsanız, bunu çok fazla karmaşıklık olmadan halledebilirsiniz. P / Invoke ile yerel kütüphaneler hakkında konuşuyorsanız, yapılması gereken biraz daha var. Ancak, yalnızca bir platformda bulunan kitaplıklarla bağlantı kuruyorsanız, büyük olasılıkla birden fazla derleme kullanmanız gerekecektir.

Harici uygulamalar

Muhtemelen #ifbu durumda ifadeler kullanmanıza gerek yoktur . Sadece bazı arayüzler kurun ve platform başına bir uygulamaya sahip olun. Platformu algılamak ve doğru örneği sağlamak için bir fabrika kullanın.

Bazı durumlarda, yalnızca belirli bir platform için derlenmiş bir ikili dosyadır, ancak çalıştırılabilir dosyanın adı ve tüm parametreler aynı şekilde tanımlanır. Bu durumda, doğru çalıştırılabilir dosyayı çözme meselesi. Windows ve Linux'ta çalışabilen bir toplu ses dönüştürücü uygulaması için, ikili adı çözmek için statik bir başlatıcı vardı.

public class AudioProcessor
{
    private static readonly string AppName = "lame";
    private static readonly string FullAppPath;

    static AudioProcessor()
    {
        var platform = DetectPlatform();
        var architecture = Detect64or32Bits();

        FullAppPath = Path.combine(platform, architecture, AppName);
    }
}

Burada süslü bir şey yok. Sadece iyi ol moda sınıfları.

P / çağırır

P / Invoke biraz daha hileli. Sonuç olarak, yerel kütüphanenin doğru sürümünün yüklendiğinden emin olmanız gerekir. Pencerelerde P / Invoke olur SetDllDirectory(). Farklı platformların bu adıma ihtiyacı olmayabilir. İşte işler burada dağınık olabilir. #ifÖzellikle dağıtım paketinize ekliyorsanız, kütüphane yolunuzun çözümlenmesini denetlemek için hangi çağrının kullanılacağını kontrol etmek için ifadeler kullanmanız gerekebilir .

Tamamen farklı platforma bağımlı kütüphanelere bağlanma

Eski okul çoklu hedefleme yaklaşımı burada yararlı olabilir. Ancak çok çirkinlik ile geliyor. Bazı projelerin aynı DLL hedef Silverlight, WPF ve potansiyel olarak UAP'yi kullanmaya çalıştığı günlerde, uygulamayı farklı derleme etiketleriyle birden çok kez derlemeniz gerekir. Yukarıdaki platformların her biriyle ilgili zorluk, aynı kavramları paylaşırken, platformların bu farklılıklar üzerinde çalışmanızdan yeterince farklı olmasıdır. Burası cehenneme giriyoruz #if.

Bu yaklaşım, .csprojplatforma bağımlı referansları işlemek için dosyayı elle düzenlemeyi de gerektirir . Senin bu yana .csprojdosya bir MSBuild dosyasıdır, bilinen bir ve öngörülebilir bir şekilde yapmak tamamen mümkün.

# cehennem

Kodlar bölümlerini #ifdeyimler kullanarak açıp kapatabilirsiniz, böylece uygulamalar arasındaki küçük farkların ele alınmasında etkili olur. Yüzeyde iyi bir fikir gibi geliyor. Hatta çizim kodunda hata ayıklamak için sınırlayıcı kutu görselleştirmeyi açmak ve kapatmak için bir araç olarak kullandım.

İle 1 numaralı sorun #ifolduğunu hiçbiri ayrıştırıcı tarafından değerlendirilir kapatılır kod. Gizli sözdizimi hataları veya daha da kötüsü, kitaplığı yeniden derlemenizi bekleyen mantık hataları olabilir. Bu, yeniden düzenleme koduyla daha da sorunlu hale gelir. Bir yöntemi yeniden adlandırmak veya parametrelerin sırasını değiştirmek kadar basit bir şey normal olarak ele alınacaktır, ancak ayrıştırıcı #ififadeyle kapatılan hiçbir şeyi değerlendirmediği için, aniden yeniden derleyene kadar göremeyeceğiniz bozuk bir kodunuz vardır.

Bu şekilde yazılmış tüm hata ayıklama kodum, bir dizi yeniden düzenleme işlemi kırıldıktan sonra yeniden yazılmak zorunda kaldı. Yeniden yazma sırasında, bu özellikleri açmak ve kapatmak için genel bir yapılandırma sınıfı kullandım. Bu, aracı yeniden kanıtladı, ancak böyle bir çözüm, API tamamen farklı olduğunda yardımcı olmaz.

Tercih ettiğim yöntem

Öğrenilen birçok acı verici derse ve hatta Microsoft'un kendi örneğine dayalı olarak tercih ettiğim yöntem, birden fazla derleme kullanmaktır.

Bir çekirdek NetStandard derlemesi tüm arabirimleri tanımlar ve tüm ortak kodu içerir. Platforma bağlı uygulamalar, dahil edildiğinde özellikler ekleyecek ayrı bir montajda olacaktır.

Bu yaklaşım, yeni Yapılandırma API'sı ve mevcut Kimlik mimarisi ile örneklenmiştir. Daha spesifik entegrasyonlara ihtiyacınız olduğu için, bu yeni montajları eklemeniz yeterlidir. Bu montajlar ayrıca kendi kurulumunuza dahil etmek için uzatma işlevleri sağlar. Bir bağımlılık enjeksiyon yaklaşımı kullanıyorsanız, bu genişletme yöntemleri kitaplığın hizmetlerini kaydetmesine izin verir.

Bu, #ifcehennemden kaçınmanın ve oldukça farklı bir ortamı tatmin etmenin tek yolu hakkında .


C # (yaklaşık 18 yıldır C ++ ve yaklaşık yarım gün C # kullandık, bu beklenen) emmek. Bu yeni yapılandırma ... buna bazı bağlantılar verebilir misiniz? Kendi başıma bulamıyorum.
Daha temiz

2
docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/… Ek yapılandırma kaynakları eklemek için birden fazla Nuget paketi vardır. Örneğin, ortam değişkenlerinden, JSON dosyalarından vb.
Berin Loritsch

1
Bu var Microsoft.Extensions.ConfigurationAPI'leri kümesi.
Berin Loritsch

1
İşte kök github projesi: github.com/aspnet/Configuration
Berin Loritsch
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.