Yansıma yoluyla çağrılan bir yöntemi işaretlemek için en iyi uygulama?


11

Yazılımımız, yansıma yoluyla dinamik olarak bulunması gereken birkaç sınıfa sahiptir. Sınıfların hepsinde, yansıma kodunun nesneleri başlattığı belirli bir imzası olan bir kurucu vardır.
Ancak, birisi yönteme başvurulup uyulmadığını kontrol ettiğinde (örneğin, Visual studio Code Lens aracılığıyla), yansıma yoluyla başvuru sayılmaz. İnsanlar referanslarını kaçırabilir ve görünüşte kullanılmayan yöntemleri kaldırabilir (veya değiştirebilir).

Yansıtma yoluyla çağrılması amaçlanan yöntemleri nasıl işaretlemeliyiz / belgelemeliyiz?

İdeal olarak, yöntem, hem meslektaşlar hem de Visual Studio / Roslyn ve diğer otomatik araçlar, yöntemin yansıma yoluyla çağrılmasını amaçladığı 'görecek' şekilde işaretlenmelidir.

Kullanabileceğimiz iki seçenek biliyorum ama ikisi de tatmin edici değil. Visual Studio başvuruları bulamadığından:

  • Özel bir Öznitelik kullanın ve yapıcıyı bu öznitelikle işaretleyin.
    • Sorun, öznitelik özelliklerinin bir yöntem başvurusu olamamasıdır, bu nedenle yapıcı yine de 0 başvurusu olduğunu gösterir.
    • Özel özniteliğe aşina olmayan meslektaşlar muhtemelen görmezden gelecektir.
    • Mevcut yaklaşımımın bir avantajı, yansıtma kısmının, çağırması gereken yapıcıyı bulmak için niteliği kullanabilmesidir.
  • Bir yöntemin / kurucunun yansıma yoluyla çağrılması amaçlandığını belgelemek için yorumları kullanın.
    • Otomatik araçlar yorumları yok sayar (ve iş arkadaşları da bunu yapabilir).
    • Xml Belgeleri Yorumlar , Visual Studio'nun yöntem / yapıcıya ek bir başvuru sayması için kullanılabilir: Yapıcısı yansıma yoluyla çağıracak sınıf
      olsun MyPlugin. Çağıran yansıma kodunun intparametre alan kurucuları aradığını varsayalım . Aşağıdaki belgeler, kod merceğinin 1 referansa sahip kurucuyu göstermesini sağlar:
      /// <see cref="MyPlugin.MyPlugin(int)"/> is invoked via reflection

Hangi daha iyi seçenekler var?
Yansıma yoluyla çağrılması amaçlanan bir yöntemi / kurucuyu işaretlemek için en iyi uygulama hangisidir?


Açıkçası, bu bir çeşit eklenti sistemi için, değil mi?
whatsisname

2
İş arkadaşlarınızın yaptığınız her şeyi görmezden geleceklerini ya da özleyeceklerini varsayıyorsunuz ... Kodun işte böyle bir verimsizliğe sahip olmasını engelleyemezsiniz. Dokümantasyon bana daha kolay, daha temiz, daha ucuz ve tavsiye edilebilir bir yol gibi geliyor. Aksi takdirde bildirimsel programlama mevcut olmaz.
Laiv

1
Yeniden Paylaşıcı [UsedImplictly] özelliğine sahiptir.
CodesInChaos

4
Sanırım Xml doc yorum seçeneği muhtemelen en iyi seçenektir. Kısa, kendi kendini belgelendirir ve herhangi bir "hack" veya ek tanımlamaya ihtiyaç duymaz.
Doc Brown

2
Xml dokümantasyon yorumları için başka bir oy. Yine de dokümantasyon oluşturuyorsanız, oluşturulan dokümantasyonda öne çıkmalıdır.
Frank Hileman

Yanıtlar:


12

Önerilen çözümlerin bir kombinasyonu:

  • Yapıcı / yöntemin yansıma yoluyla çağrıldığını belgelemek için XML Belgeleri etiketlerini kullanın.
    Bu, iş arkadaşlarına (ve gelecekteki kendime) amaçlanan kullanımı açıklığa kavuşturmalıdır.
  • <see>Yapıcı / yöntem için başvuru sayısını artırmak için -tag ile 'hile' kullanın .
    Bu, kod merceğinin ve bulma referanslarının yapıcı / yönteme başvurulduğunu göstermesini sağlar.
  • Resharper's ile açıklama ekleyin UsedImplicitlyAttribute
    • Yeniden birleştirici fiili bir standarttır ve [UsedImplicitly]tam olarak tasarlanan anlambilime sahiptir.
    • Resharper kullanmayanlar JetBrains ReSharper Ek Açıklamalarını NuGet:
      PM> aracılığıyla yükleyebilir Install-Package JetBrains.Annotations.
  • Bu özel bir yöntemse ve Visual Studio'nun kod analizini kullanıyorsanız SupressMessageAttribute, ileti için kullanın CA1811: Avoid uncalled private code.

Örneğin:

class MyPlugin
{
    /// <remarks>
    /// <see cref="MyPlugin.MyPlugin(int)"/> is called via reflection.
    /// </remarks>
    [JetBrains.Annotations.UsedImplicitly]
    public MyPlugin(int arg)
    {
        throw new NotImplementedException();
    }

    /// <remarks>
    /// <see cref="MyPlugin.MyPlugin(string)"/> is called via reflection.
    /// </remarks>
    [JetBrains.Annotations.UsedImplicitly]
    [System.Diagnostics.CodeAnalysis.SuppressMessage(
        "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode",
        Justification = "Constructor is called via reflection")]
    private MyPlugin(string arg)
    {
        throw new NotImplementedException();
    }
}

Çözüm, kurucunun hem insan okuyuculara hem de C # ve Visual Studio ile en çok kullanılan 3 statik kod analiz sistemine amaçlanan kullanımını sağlar.
Olumsuz yanı, hem bir yorum hem de bir veya iki ek açıklama biraz gereksiz görünebilir.


Not da var MeansImplicitUseAttributebir var kendi özelliklerini yapmak için kullanılabileceğini UsedImplicitlyetkisi. Bu, doğru durumlarda çok fazla nitelik gürültüsünü azaltabilir.
Dave Cousineau

JetBrains bağlantısı kesildi.
John Zabroski

5

Bu sorunu bir .Net projesinde hiç yaşamadım, ancak Java projelerinde düzenli olarak aynı sorunu yaşıyorum. Her zamanki yaklaşımım @SuppressWarnings("unused")açıklamayı, nedenini açıklayan bir yorum ekleyerek kullanmaktır (herhangi bir uyarıyı devre dışı bırakma nedenini belgelemek standart kod stilimin bir parçasıdır - derleyici bir şey çözemediğinde, bir insanın çok). Bunun avantajı, statik analiz araçlarının kodun doğrudan referansları olmadığı ve insan okuyucular için ayrıntılı bir sebep vermediğinin farkında olmalarını sağlamaktır.

Java'nın C # eşdeğer @SuppressWarningsolduğunu SuppressMessageAttribute. İçin özel yöntemlerle mesajın kullanabilirsiniz CA1811: yersiz özel kod kaçının ; Örneğin:

class MyPlugin
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage(
        "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode",
        Justification = "Constructor is called via reflection")]
    private MyPlugin(int arg)
    {
        throw new NotImplementedException();
    }
}

(Bilmiyorum, ancak CLI'nın bahsettiğim Java'ya benzer bir özelliği desteklediğini varsayalım; kimse ne olduğunu biliyorsa, cevabımı referans olarak düzenleyin ...)
Jules


1
Son zamanlarda testler ve kapsam (java) mesuring bir kod bloğunun gerçekten kullanılmadığını bilmek için iyi bir yol olduğunu keşfettim. Sonra kaldırabilir veya neden kullanılmıyor (tersini bekliyorsam) bakabilirsiniz. Arama yaparken yorumlara daha fazla dikkat ettiğim zamandır.
Laiv

Orada var olan SuppressMessageAttribute( msdn.microsoft.com/en-us/library/... ). En yakın gelen mesaj CA1811: Avoid uncalled private code( msdn.microsoft.com/en-us/library/ms182264.aspx ); Genel kod için henüz bir mesaj bulamadım.
Kasper van den Berg

2

Belgelemeye bir alternatif, yansıma çağrılarının başarılı bir şekilde çalıştığından emin olmak için birim test (ler) i yapmaktır.

Bu şekilde, bir kişi derleme / test işleminizin yöntemlerini değiştirir veya kaldırırsa, bir şeyleri kırdığınızı size bildirmelidir.


0

Kodunuzu görmeden, bu tür sesler, bazı mirasları tanıtmak için iyi bir yer olurdu. Belki de bu sınıfların kurucusunun arayabileceği sanal veya soyut bir yöntem? Eğer işaretlemek istediğiniz yöntem sadece yapıcı olduğunu, o zaman gerçekten bir yöntemi değil, bir sınıf işaretlemek için çalışıyoruz evet? Geçmişte sınıfları işaretlemek için yaptığım bir şey boş bir arayüz yapmak. Daha sonra kod denetleme araçları ve yeniden düzenleme, arabirimi uygulayan sınıfları arayabilir.


Gerçek normalde kalıtım bu şekilde olur. Ve sınıflar gerçekten mirasla ilişkilidir. Ancak mirasın ötesinde yeni bir örnek yaratmak. Ayrıca, statik yöntemlerin 'kalıtımına' güveniyorum ve C # sınıf yuvalarını desteklemediğinden; kullandığım bir yol var, ama bu yorumun kapsamı dışında.
Kasper van den Berg
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.