Làm cách nào để đóng gói các biến 'toàn cầu' trong C #? /thực hành tốt nhất


9

Trong C #, cách thực hành tốt nhất để đóng gói các biến tôi cần sử dụng trong nhiều phương thức là gì? Có thể chỉ cần khai báo chúng ở đầu lớp của tôi trên hai phương thức không?

Ngoài ra nếu tôi đang sử dụng cài đặt ứng dụng từ tệp cấu hình của mình thì tôi có nên sử dụng getter không? như thế này...

private string mySetting{ get { return WebConfigurationManager.AppSettings["mySetting"]; } }

Thực hành tốt nhất là gì?


Mục đích của một getter là gì, ngoài việc thêm một lớp bổ sung (và có thể không cần thiết)?
Robert Harvey

4
Một getter tốt hơn nhiều so với nhiều cuộc gọi đến WebConfigurationManager.AppSettingsvì việc thay đổi sau này dễ dàng hơn nhiều
Daniel Little

@Lavinski: Chắc chắn, nếu bạn nghĩ rằng bạn có thể trao đổi kho dữ liệu cho một kho khác sau này. Trong thực tế, điều đó hiếm khi xảy ra và khả năng nó có thể xảy ra đối với AppSinstall dường như rất nhỏ.
Robert Harvey

10
Một "getter" có lợi thế là nó làm cho intellisense hoạt động - và bạn có chuỗi khóa "mySetting" (không được trình biên dịch kiểm tra nếu nó được viết chính xác) chỉ ở một nơi.
Doc Brown

Câu trả lời:


5

Nó không chỉ ổn. Theo cuốn sách Clean Code, đây thực sự là một cách thực hành rất tốt và chú Bob thực sự khuyến khích điều đó. Một biến được sử dụng bởi nhiều phương thức có thể cho thấy mức độ gắn kết cao giữa các phương thức. Hơn nữa, một mức độ cao của các biến đối tượng cũng có thể gợi ý rằng lớp nên được chia làm hai để khai báo chúng là biến đối tượng có thể giúp bạn tìm ra các ứng cử viên lớp ẩn.

Biến cấp đối tượng không phải là biến toàn cục, vì vậy đừng ngại sử dụng chúng nếu chúng được chia sẻ bằng nhiều phương pháp khác nhau.


cảm ơn sự giúp đỡ của bạn, mặc dù tôi nghĩ khi bạn nói sự gắn kết, bạn thực sự có nghĩa là khớp nối.
dùng1944367

Không, ý tôi là sự gắn kết. Trên lớp Kỹ thuật phần mềm, tôi cũng có một khoảng thời gian khó khăn để hiểu được mong muốn về sự gắn kết cao. Thông thường chúng ta ham muốn sau khi khớp nối thấp và độ gắn kết cao. Khớp nối là một thứ vật lý mà chúng ta có thể thấy trên các phương pháp của chính mình. Nếu một lớp sử dụng một lớp khác, thì nó được ghép với nó. Nếu nó thực sự bắt đầu và là đối tượng của lớp đã nói, thì nó rất hợp với nó. Tuy nhiên, sự gắn kết là một điều hợp lý. Sự gắn kết cao trong một lớp có nghĩa là các phương thức của nó thuộc về một miền rất giống nhau, ngay cả khi chúng không chia sẻ bất kỳ biến nào giữa chúng.
Uri

Các phương thức khác nhau sử dụng một biến đối tượng không nhất thiết có nghĩa là chúng được ghép với nhau. Tôi có thể có một lớp Encrypter với biến mật khẩu char [] và có Encrypt (chuỗi văn bản); và Giải mã (chuỗi văn bản); phương pháp bên trong nó. Cả hai đều sử dụng cùng một biến mật khẩu, nhưng không có sự kết hợp rõ ràng giữa chúng. Tuy nhiên, bạn có thể nhận thấy rằng họ xử lý cùng một tên miền và đó là mã hóa văn bản. Theo tôi biết, họ có mức độ gắn kết cao, mặc dù nói rằng lớp học có thể được chia làm hai. Người ta có thể lập luận rằng mã hóa không thuộc về lĩnh vực giải mã.
Uri

4

Đóng gói các thiết lập của bạn một cách liên tục là một ý tưởng tuyệt vời.

Những gì tôi làm là tạo một lớp cài đặt hoặc một lớp toàn cầu tĩnh hoặc nhiều lớp đối tượng mà sau đó tôi sẽ quản lý bằng phép nội xạ phụ thuộc. Sau đó, tôi tải tất cả các cài đặt từ cấu hình vào lớp đó khi khởi động.

Tôi cũng đã viết một thư viện nhỏ sử dụng sự phản chiếu để làm cho việc này trở nên dễ dàng hơn.

Khi cài đặt của tôi nằm trong tệp cấu hình của tôi

<?xml version="1.0" encoding="utf-8" ?>
<configuration>   
    <appSettings>
        <add key="Domain" value="example.com" />
        <add key="PagingSize" value="30" />
        <add key="Invalid.C#.Identifier" value="test" />
    </appSettings>
</configuration>

Tôi tạo một lớp tĩnh hoặc cá thể tùy thuộc vào nhu cầu của tôi. Đối với các ứng dụng đơn giản chỉ có một vài cài đặt, một lớp tĩnh là ổn.

private static class Settings
{
    public string Domain { get; set; }

    public int PagingSize { get; set; }

    [Named("Invalid.C#.Identifier")]
    public string ICID { get; set; }

}

Sau đó, sử dụng thư viện của tôi gọi một trong hai Inflate.Statichoặc Inflate.Instanceđiều thú vị là tôi có thể sử dụng bất kỳ nguồn giá trị quan trọng nào.

using Fire.Configuration;

Inflate.Static( typeof(Settings), x => ConfigurationManager.AppSettings[x] );

Tất cả mã cho điều này là trong GitHub tại https://github.com/Enexure/Enexure.Fire.Configuration

Thậm chí còn có một gói nuget:

PM> Cài đặt-Gói Enexure.Fire.Configuration

Mã để tham khảo:

using System;
using System.Linq;
using System.Reflection;
using Fire.Extensions;

namespace Fire.Configuration
{
    public static class Inflate
    {
        public static void Static( Type type, Func<string, string> dictionary )
        {
            Fill( null, type, dictionary );
        }

        public static void Instance( object instance, Func<string, string> dictionary )
        {
            Fill( instance, instance.GetType(), dictionary );
        }


        private static void Fill( object instance, Type type, Func<string, string> dictionary ) 
        {

            PropertyInfo[] properties;
            if (instance == null) {

                // Static
                properties = type.GetProperties( BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly );
            } else {

                // Instance
                properties = type.GetProperties( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly );
            }

            // Get app settings and convert
            foreach (PropertyInfo property in properties) {
                var attributes = property.GetCustomAttributes( true );
                if (!attributes.Any( x => x is Ignore )) {

                    var named = attributes.FirstOrDefault( x => x is Named ) as Named;

                    var value = dictionary((named != null)? named.Name : property.Name);

                    object result;
                    if (ExtendConversion.ConvertTo(value, property.PropertyType, out result)) {
                        property.SetValue( instance, result, null );
                    }
                }
            }
        }
    }
}
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.