Thực hành tốt nhất để đánh dấu một phương pháp được gọi thông qua sự phản ánh?


11

Phần mềm của chúng tôi có một số lớp nên được tìm thấy động thông qua sự phản chiếu. Tất cả các lớp đều có một hàm tạo với một chữ ký cụ thể thông qua đó mã phản chiếu sẽ khởi tạo các đối tượng.
Tuy nhiên, khi ai đó kiểm tra xem phương thức có được tham chiếu hay không (ví dụ qua Visual Studio Code Lens), tham chiếu qua phản chiếu không được tính. Mọi người có thể bỏ lỡ các tài liệu tham khảo của họ và loại bỏ (hoặc thay đổi) các phương thức rõ ràng không được sử dụng.

Làm thế nào chúng ta nên đánh dấu / phương pháp tài liệu dự định được gọi thông qua sự phản ánh?

Lý tưởng nhất, phương pháp nên được đánh dấu theo cách mà cả đồng nghiệp và Visual Studio / Roslyn và các công cụ tự động khác 'thấy' rằng phương thức này được dự định sẽ được gọi thông qua sự phản chiếu.

Tôi biết hai tùy chọn mà chúng ta có thể sử dụng nhưng cả hai đều không hoàn toàn thỏa mãn. Vì Visual Studio không thể tìm thấy các tài liệu tham khảo:

  • Sử dụng Thuộc tính tùy chỉnh và đánh dấu hàm tạo với thuộc tính này.
    • Một vấn đề là thuộc tính Thuộc tính không thể là tham chiếu phương thức, do đó hàm tạo sẽ vẫn hiển thị là có 0 tham chiếu.
    • Các đồng nghiệp không quen thuộc với thuộc tính tùy chỉnh có thể sẽ bỏ qua nó.
    • Một lợi thế của cách tiếp cận hiện tại của tôi là phần phản chiếu có thể sử dụng thuộc tính để tìm hàm tạo mà nó sẽ gọi.
  • Sử dụng các ý kiến ​​để ghi lại rằng một phương thức / hàm tạo được dự định được gọi thông qua sự phản chiếu.
    • Các công cụ tự động bỏ qua các bình luận (và các đồng nghiệp cũng có thể làm như vậy).
    • Nhận xét Tài liệu Xml có thể được sử dụng để Visual Studio đếm một tham chiếu bổ sung cho phương thức / hàm tạo:
      Hãy MyPluginlà lớp có hàm tạo để gọi thông qua sự phản chiếu. Giả sử tìm kiếm mã phản chiếu tìm kiếm các hàm tạo có inttham số. Tài liệu sau đây làm cho ống kính mã đó hiển thị hàm tạo có 1 tham chiếu:
      /// <see cref="MyPlugin.MyPlugin(int)"/> is invoked via reflection

Những lựa chọn tốt hơn tồn tại?
Cách thực hành tốt nhất để đánh dấu một phương thức / hàm tạo được dự định gọi qua phản xạ là gì?


Để rõ ràng, đây là cho một số loại hệ thống plugin, phải không?
whatsisname

2
Bạn đang cho rằng đồng nghiệp của bạn sẽ phớt lờ hoặc bỏ lỡ mọi thứ bạn làm ... Bạn không thể ngăn chặn mã không hiệu quả như vậy trong công việc. Tài liệu dường như với tôi cách dễ dàng hơn, sạch hơn, rẻ hơn và khuyên. Nếu không sẽ không tồn tại các chương trình khai báo.
Laiv

1
Resharper có thuộc tính [usedImplictly].
CodeInChaos

4
Tôi đoán tùy chọn nhận xét tài liệu Xml có lẽ là tùy chọn tốt nhất của bạn. Nó ngắn, tự viết tài liệu và không cần bất kỳ "hack" hoặc định nghĩa bổ sung nào.
Doc Brown

2
Một phiếu khác cho ý kiến ​​tài liệu xml. Nếu bạn đang tạo tài liệu nào, nó sẽ nổi bật trong tài liệu được tạo.
Frank Hileman

Câu trả lời:


12

Một sự kết hợp của các giải pháp được đề xuất:

  • Sử dụng các thẻ Tài liệu XML để ghi lại rằng hàm tạo / phương thức được gọi thông qua sự phản chiếu.
    Điều này sẽ làm rõ việc sử dụng dự định cho các đồng nghiệp (và bản thân tương lai của tôi).
  • Sử dụng 'mẹo' thông qua <see>-tag để tăng số tham chiếu cho phương thức / phương thức xây dựng.
    Điều này làm cho ống kính mã đó và tìm các tham chiếu cho thấy hàm tạo / phương thức được tham chiếu.
  • Chú thích với Resharper's UsedImplicitlyAttribute
    • Resharper là một tiêu chuẩn thực tế và [UsedImplicitly]có chính xác ngữ nghĩa dự định.
    • Những người không sử dụng Resharper có thể cài đặt Chú thích ReSharper của JetBrains qua NuGet:
      PM> Install-Package JetBrains.Annotations.
  • Nếu đó là một phương thức riêng tư và bạn đang sử dụng phân tích mã của Visual Studio, hãy sử dụng SupressMessageAttributecho thông báo CA1811: Avoid uncalled private code.

Ví dụ:

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

Giải pháp dành cho mục đích sử dụng của hàm tạo cho cả người đọc và 3 hệ thống phân tích mã tĩnh được sử dụng nhiều nhất với C # và Visual Studio.
Nhược điểm là cả một bình luận và một hoặc hai chú thích có vẻ hơi dư thừa.


Lưu ý MeansImplicitUseAttributerằng cũng có thể được sử dụng để làm cho các thuộc tính của riêng bạn có UsedImplicitlyhiệu lực. Điều này có thể làm giảm rất nhiều tiếng ồn thuộc tính trong các tình huống phù hợp.
Dave Cousineau

Liên kết đến JetBrains bị hỏng.
John Zabroski

5

Tôi chưa bao giờ gặp vấn đề này trong một dự án .Net, nhưng tôi thường gặp vấn đề tương tự với các dự án Java. Cách tiếp cận thông thường của tôi là sử dụng @SuppressWarnings("unused")chú thích thêm một nhận xét giải thích lý do (ghi lại lý do vô hiệu hóa bất kỳ cảnh báo nào là một phần của kiểu mã tiêu chuẩn của tôi - bất cứ khi nào trình biên dịch không thể tìm ra điều gì đó, tôi cho rằng có khả năng con người có thể đấu tranh quá). Điều này có lợi thế là tự động đảm bảo các công cụ phân tích tĩnh nhận thức được rằng mã không được phép có các tham chiếu trực tiếp và đưa ra lý do chi tiết cho người đọc.

Tương đương C # của Java @SuppressWarningsSuppressMessageAttribute. Đối với các phương thức riêng tư, bạn có thể sử dụng thông báo CA1811: Tránh mã riêng chưa được xử lý ; ví dụ:

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

(Tôi không biết, nhưng giả sử rằng CLI hỗ trợ một thuộc tính tương tự như Java mà tôi đã đề cập; nếu có ai biết nó là gì, vui lòng chỉnh sửa câu trả lời của tôi để tham chiếu đến nó ...)
Jules

stackoverflow.com/q/10926385/5934037 trông giống như Nó.
Laiv

1
Gần đây tôi đã phát hiện ra rằng việc thực hiện các thử nghiệm và bảo hiểm mê hoặc (trong java) là một cách tốt để biết liệu một khối mã có thực sự không được sử dụng hay không. Sau đó, tôi có thể loại bỏ nó hoặc xem tại sao Không sử dụng (nếu tôi mong đợi điều ngược lại). Trong khi tìm kiếm là khi tôi chú ý hơn đến các ý kiến.
Laiv

Tồn tại SuppressMessageAttribute( msdn.microsoft.com/en-us/l Library / Google ). Thông báo đến gần nhất là CA1811: Avoid uncalled private code( msdn.microsoft.com/en-us/l Library / ms182264.aspx ); Tôi chưa tìm thấy một tin nhắn cho mã công khai.
Kasper van den Berg

2

Một cách khác để ghi lại tài liệu sẽ là có (các) bài kiểm tra đơn vị để đảm bảo rằng các cuộc gọi phản xạ chạy thành công.

Theo cách đó, nếu ai đó thay đổi hoặc loại bỏ các phương thức quy trình xây dựng / kiểm tra của bạn sẽ cảnh báo bạn rằng bạn đã làm hỏng một cái gì đó.


0

Chà mà không thấy mã của bạn, loại âm thanh như thế này sẽ là một nơi tốt để giới thiệu một số thừa kế. Có lẽ một phương thức ảo hoặc trừu tượng mà hàm tạo của các lớp này có thể gọi? Nếu bạn là phương thức bạn đang cố gắng đánh dấu chỉ là hàm tạo, thì bạn có thực sự đang cố gắng đánh dấu một lớp chứ không phải là một phương thức yeah? Một cái gì đó tôi đã làm trong quá khứ để đánh dấu các lớp là tạo một giao diện trống. Sau đó, các công cụ kiểm tra mã và tái cấu trúc có thể tìm kiếm các lớp thực hiện giao diện.


Đúng là thừa kế thông thường sẽ là con đường đi. Và các lớp thực sự có liên quan bởi sự kế thừa. Nhưng tạo ra một ví dụ mới trong việc thừa kế. Ngoài ra, tôi dựa vào 'sự kế thừa' của các phương thức tĩnh và vì C # không hỗ trợ các vị trí lớp; có một cách xung quanh, mà tôi sử dụng, nhưng đó là ngoài phạm vi của nhận xét này.
Kasper van den Berg
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.