.NET: Ngoại lệ nào cần ném khi thiếu cài đặt cấu hình bắt buộc?


123

Đây là một kịch bản tiêu chuẩn:

if(string.IsNullOrEmpty(Configuration.AppSettings["foobar"]))
   throw new SomeStandardException("Application not configured correctly, bozo.");

Vấn đề là, tôi không hoàn toàn chắc chắn đó là ngoại lệ SomeStandardExceptionnên.

Tôi đã xem xét Khung 3.5 và tìm thấy hai ứng cử viên có khả năng: ConfigurationExceptionConfigurationErrorsException.

System.Configuration.ConfigurationException

Ngoại lệ được ném ra khi xảy ra lỗi hệ thống cấu hình.

Nhận xét

Các ConfigurationExceptionngoại lệ được ném nếu những nỗ lực ứng dụng để đọc hoặc ghi dữ liệu vào tập tin cấu hình nhưng không thành công. Một số lý do có thể xảy ra cho điều này có thể bao gồm XML không đúng định dạng trong tệp cấu hình, các vấn đề về quyền đối với tệp và các thuộc tính cấu hình có giá trị không hợp lệ.

Ghi chú:

Đối ConfigurationExceptiontượng được duy trì để tương thích ngược. Đối ConfigurationErrorsException tượng thay thế nó cho hệ thống cấu hình.

Ngoại lệ này thực sự nghe có vẻ hoàn hảo cho những gì tôi cần, nhưng nó đã bị đánh dấu là lỗi thời, vì vậy, ixnay trên atthay.

Điều này khiến chúng ta hoàn toàn khó hiểu ConfigurationErrorsException:

System.Configuration.ConfigurationErrorsException

Giá trị hiện tại không phải là một trong các giá trị EnableSessionState.

Như bạn có thể thấy, tài liệu của nó là hoàn toàn vô dụng. (Đó là cách làm trong cả trợ giúp địa phương và trực tuyến.) Bản thân việc kiểm tra lớp học cho thấy rằng nó quá mức cần thiết cho những gì tôi muốn.

Tóm lại, tôi cần một ngoại lệ tiêu chuẩn sẽ được ném khi cài đặt cấu hình ứng dụng bị thiếu hoặc chứa giá trị không hợp lệ. Bạn sẽ nghĩ rằng Framework có một ngoại lệ như vậy được đưa vào nó để các ứng dụng sử dụng. (Rõ ràng là có, nhưng nó bị đánh dấu là lỗi thời và được thay thế bằng thứ gì đó phạm vi lớn hơn nhiều .)

Các giải pháp nào, nếu có, các bạn đang sử dụng cho việc này, và tôi sẽ phải bỏ qua và đưa ra ngoại lệ của riêng mình cho việc này?

Chỉnh sửa Addenda

Một số đã hỏi liệu tôi có thể cung cấp giá trị mặc định hay không và tiếp tục. Trong một số trường hợp, có, và trong những trường hợp đó, ngoại lệ sẽ không được ném ra. Tuy nhiên, đối với một số cài đặt nhất định, điều này sẽ không áp dụng. Ví dụ: tên máy chủ cơ sở dữ liệu và thông tin đăng nhập, máy chủ xác thực và đường dẫn đến các ứng dụng bên thứ ba đã cài đặt.

Cũng cần lưu ý rằng ứng dụng mà tôi chủ yếu đang làm việc là một ứng dụng bảng điều khiển chạy ở chế độ hàng loạt và tôi muốn nó đưa ra một ngoại lệ được phương thức chính bắt và ghi lại một cách thích hợp nếu thứ đó không được định cấu hình thích hợp. (Đó là mã kế thừa mà tôi đã kế thừa và hiện tại chỉ giả định mọi thứ đều ổn.)


1
Tài liệu cho System.Configuration.ConfigurationErrorsException đã được cập nhật.
slolife

Câu trả lời:


36

Bạn không bị giới hạn trong việc ném ngoại lệ của mình đối với các ngoại lệ hiện có trong Khung. Nếu bạn quyết định sử dụng các trường hợp ngoại lệ hiện có, bạn không nhất thiết phải làm theo tài liệu về bức thư. Tài liệu sẽ mô tả cách khung sử dụng một ngoại lệ nhất định, nhưng không ngụ ý bất kỳ giới hạn nào về cách bạn chọn sử dụng / sử dụng lại một ngoại lệ hiện có.

Đó là ứng dụng của bạn - miễn là bạn ghi lại nó và chỉ ra rõ ràng ngoại lệ sẽ được đưa ra trong trường hợp cụ thể là thiếu giá trị cấu hình, bạn có thể sử dụng bất kỳ ngoại lệ nào bạn thích. Nếu bạn muốn một chỉ báo rất cụ thể về một giá trị bị thiếu , bạn có thể cân nhắc viết ngoại lệ ConfigurationSettingMissing của riêng mình:

[Serializable]
public class ConfigurationMissingException : ConfigurationErrorsException
{}

CHỈNH SỬA: Viết ngoại lệ của riêng bạn trong trường hợp này mang lại lợi ích bổ sung là đảm bảo rằng sẽ không bao giờ có bất kỳ sự nhầm lẫn nào về việc ngoại lệ đến từ đâu- khuôn khổ hoặc ứng dụng của bạn. Khuôn khổ sẽ không bao giờ ném các ngoại lệ tùy chỉnh của bạn.

CẬP NHẬT: Tôi đồng ý với các nhận xét, vì vậy tôi đã thay đổi lớp con thành ConfigurationErrorsException từ Exception. Tôi nghĩ thông thường nên phân lớp ngoại lệ tùy chỉnh từ các ngoại lệ Framework hiện có nếu có thể, tránh lớp Exception trừ khi bạn cần một ngoại lệ dành riêng cho ứng dụng.


17
Tôi không đồng ý phần nào. Nếu bạn định sử dụng một ngoại lệ hiện có, nó nên được sử dụng CHÍNH XÁC như tài liệu cho biết nó đã được sử dụng, nếu không bạn sẽ nhầm lẫn với những người đến sau bạn. Nếu bạn định làm điều gì đó khác biệt, chỉ cần tạo ngoại lệ của riêng bạn, như bạn đã nói.
Robert C. Barth

1
Tôi không đồng ý. Trừ khi bạn có một kịch bản để bắt ngoại lệ tùy chỉnh của mình, không xảy ra trong trường hợp lỗi cấu hình, tốt hơn nên sử dụng lại Loại hiện có (ConfigurationErrorsException). Và nếu bạn tạo một Loại tùy chỉnh, tôi sẽ lấy nó từ một Loại liên quan, chẳng hạn như ConfigurationErrorsException.
Joe

@Robert & Joe- Tôi không gợi ý rằng các ngoại lệ Framework hiện tại nên được sử dụng không nhất quán với chức năng dự định của chúng, chỉ là có một số tính linh hoạt miễn là trường hợp cụ thể (giá trị bị thiếu) phù hợp với trường hợp chung (ConfigurationErrorsException).
Dave Swersky

1
Có thể có sự cố với điều này nếu bạn đang ném ngoại lệ trong ứng dụng ASP.NET dưới dạng ConfigurationErrorsException và các lớp bắt nguồn từ nó không bị bắt trong phương thức OnError được bảo vệ hoặc bởi sự kiện Global ASAX Error. Xem câu hỏi này mà tôi đã đăng .... stackoverflow.com/questions/25299325/…
Mick

48

Cá nhân tôi sử dụng InvalidOperationException , vì đó là vấn đề với trạng thái đối tượng - không phải hệ thống cấu hình. Rốt cuộc, bạn không nên cho phép các cài đặt này được đặt bằng mã và không phải cấu hình? Phần quan trọng ở đây không phải là không có dòng nào trong app.config, mà là phần thông tin bắt buộc không có.

Đối với tôi, ConfigurationException (và nó thay thế, ConfigurationErrorsException - mặc dù tài liệu MSDN gây hiểu lầm) dành cho các lỗi khi lưu, đọc, v.v. của Cấu hình.


Tôi đã chọn cho InvalidOperationException, vì nó được xử lý bởi ASP.NET trang bảo vệ phương pháp onerror, trong khi ConfigurationErrorsException và tất cả các trường hợp ngoại lệ bắt nguồn từ nó không
Mick

2
Điều này thực sự sẽ làm tôi ngạc nhiên, nếu tôi nhận được lỗi InvalidOperationException nếu tôi cấu hình sai.
keuleJ

18

Như Daniel Richardson đã nói, ConfigurationErrorsException là cái để sử dụng. Nói chung, bạn chỉ nên tạo các loại Ngoại lệ tùy chỉnh của riêng mình nếu bạn có tình huống xử lý chúng. Trong trường hợp lỗi cấu hình, thường là nghiêm trọng, trường hợp này hiếm khi xảy ra nên thường thích hợp hơn để sử dụng lại kiểu ConfigurationErrorsException hiện có.

Trước .NET 2.0, khuyến nghị là sử dụng System.Configuration.ConfigurationException . ConfigurationException đã trở nên lỗi thời trong .NET 2.0, vì những lý do mà tôi không bao giờ rõ ràng và khuyến nghị đã thay đổi để sử dụng ConfigurationErrorsException.

Tôi sử dụng phương pháp trợ giúp để ném ngoại lệ để dễ dàng thay đổi ngoại lệ đang được ném ở một nơi khi di chuyển từ .NET 1.x sang 2.0 hoặc nếu Microsoft quyết định thay đổi lại đề xuất:

if(string.IsNullOrEmpty(Configuration.AppSettings("foobar")))
{
   throw CreateMissingSettingException("foobar");
}

...

private static Exception CreateMissingSettingException(string name)
{
    return new ConfigurationErrorsException(
        String.Format
        (
        CultureInfo.CurrentCulture,
        Properties.Resources.MissingConfigSetting,
        name
        )
        );
}

16

IMO đây là câu trả lời thực sự. +1
LC

Không hẳn, bởi vì: Cung cấp một ngoại lệ cho các đối tượng SettingsProperty không được tìm thấy. Xuất phát từ: Được sử dụng nội bộ làm lớp đại diện cho siêu dữ liệu về thuộc tính cấu hình riêng lẻ. Giá trị nào không giống với giá trị bị thiếu của cấu hình.
Karol Haliński

7

ConfigurationErrorsExceptionlà ngoại lệ chính xác để ném vào tình huống bạn mô tả. Phiên bản trước của tài liệu MSDN ConfigurationErrorsExceptioncó ý nghĩa hơn.

http://msdn.microsoft.com/en-us/library/system.configuration.configurationerrorsexception(VS.80).aspx

Bản tóm tắt và nhận xét MSDN trước đó là:

  • Ngoại lệ được đưa ra khi xảy ra lỗi hệ thống cấu hình.
  • Các ConfigurationErrorsException ngoại lệ được ném ra khi bất kỳ lỗi xảy ra trong khi thông tin cấu hình đang được đọc hay viết.

7
từ tài liệu: "API này hỗ trợ cơ sở hạ tầng sản phẩm và không nhằm mục đích sử dụng trực tiếp từ mã của bạn. Khởi tạo phiên bản mới của lớp ConfigurationErrorsException."
Oleg Sh

6

Lớp ConfigurationElement (là lớp cơ sở của nhiều lớp liên quan đến cấu hình, như ConfigurationSection) có một phương thức gọi là OnRequiredPropertyNotFound (cũng có các phương thức trợ giúp khác). Bạn có thể gọi những cái đó.

OnRequiredPropertyNotFound được triển khai như thế này:

protected virtual object OnRequiredPropertyNotFound(string name) {
    throw new ConfigurationErrorsException(SR.GetString("Config_base_required_attribute_missing", new object[] { name }), this.PropertyFileName(name), this.PropertyLineNumber(name)); }

1

Tôi muốn thu thập nó và cuộn của riêng tôi ... nhưng trước khi bạn làm điều đó, Có thể để hệ thống giả định một giá trị mặc định cho cài đặt cấu hình này không? Tôi thường cố gắng thực hiện điều đó cho mọi cài đặt có thể bị bỏ sót trong dân gian Quản lý hoạt động ... (hoặc có lẽ tôi nên nói, đối với càng nhiều cài đặt càng tốt - đối với một số cài đặt, rõ ràng là không thích hợp để hệ thống đưa ra quyết định mặc định. ..)

nói chung một ngoại lệ tùy chỉnh không tốn nhiều công sức ... đây là một ví dụ ...

[Serializable]
public class MyCustomApplicationException : ApplicationException
{
    #region privates
    #endregion privates

    #region properties
    #endregion properties

    public MyCustomApplicationException (string sMessage,
        Exception innerException)
        : base(sMessage, innerException) { }
    public MyCustomApplicationException (string sMessage)
        : base(sMessage) { }
    public MyCustomApplicationException () { }

    #region Serializeable Code
    public MyCustomApplicationException (
       SerializationInfo info, StreamingContext context)
        : base(info, context) { }
    #endregion Serializeable Code
}

2
MSDN: ... một ứng dụng cần tạo các ngoại lệ của riêng nó, [...] lấy các ngoại lệ tùy chỉnh từ lớp Exception. Ban đầu, người ta nghĩ rằng các ngoại lệ tùy chỉnh nên bắt nguồn từ lớp ApplicationException; tuy nhiên trong thực tế điều này không được tìm thấy là có thêm giá trị đáng kể.
Gaspar Nagy

Vâng, tôi nghĩ đó là do các lập trình viên MS đã mã hóa khung công tác đã dẫn xuất nhiều ngoại lệ CLR từ ApplicationException, do đó phá hủy tầm quan trọng của sự khác biệt .. Mặc dù vậy, tôi vẫn làm điều đó, vì tôi thấy không có hại gì ...
Charles Bretana

1

Một phương pháp thay thế mà bạn có thể sử dụng cho các tệp cấu hình của mình sẽ là sử dụng các phần cấu hình tùy chỉnh trái ngược với AppSettings. Bằng cách đó, bạn có thể chỉ định rằng một thuộc tính IsRequiredvà hệ thống cấu hình sẽ xử lý việc kiểm tra này cho bạn. Nếu thuộc tính bị thiếu nó sẽ ném ra ConfigurationErrorsExceptionvì vậy tôi cho rằng điều đó hỗ trợ câu trả lời rằng bạn nên sử dụng ngoại lệ đó trong trường hợp của bạn.


0

Quy tắc chung của tôi sẽ là:

  1. Nếu trường hợp cấu hình bị thiếu không phải là rất phổ biến và tôi tin rằng tôi sẽ không bao giờ muốn xử lý trường hợp này khác với các trường hợp ngoại lệ khác, tôi chỉ sử dụng lớp "Ngoại lệ" cơ bản với một thông báo thích hợp:

    ném Ngoại lệ mới ("tin nhắn của tôi ở đây")

  2. Nếu tôi muốn, hoặc nghĩ rằng có khả năng cao tôi muốn xử lý trường hợp này theo một cách khác với hầu hết các trường hợp ngoại lệ khác, tôi sẽ cuộn loại của riêng mình như mọi người đã đề xuất ở đây.


0

Tôi có xu hướng không đồng ý với tiền đề câu hỏi của bạn:

Tóm lại, tôi cần một ngoại lệ tiêu chuẩn sẽ được ném khi cài đặt cấu hình ứng dụng bị thiếu hoặc chứa giá trị không hợp lệ. Bạn sẽ nghĩ rằng Framework có một ngoại lệ như vậy được đưa vào nó để các ứng dụng sử dụng. (Rõ ràng là có, nhưng nó bị đánh dấu là lỗi thời và được thay thế bằng thứ gì đó có phạm vi lớn hơn nhiều.)

Theo tài liệu MSDN trên System.Exception ( Lớp ngoại lệ , bạn thực sự không nên ném ngoại lệ cho các lỗi nhập của người dùng, vì lý do hiệu suất (đã được chỉ ra bởi những người khác trên Stack Overflow và các nơi khác). Điều này có vẻ hợp lý khi Chà - tại sao hàm của bạn không thể trả về false nếu nhập sai của người dùng và sau đó ứng dụng thoát ra một cách duyên dáng? Đây dường như là một vấn đề thiết kế nhiều hơn là một vấn đề với Exception để ném.

Như những người khác đã chỉ ra, nếu bạn thực sự phải ném một ngoại lệ - vì bất kỳ lý do gì - thì không có lý do gì khiến bạn không thể xác định loại Ngoại lệ của mình bằng cách kế thừa từ System.Exception.


2
Chính xác thì tại sao hiệu suất lại quan trọng trong kịch bản cụ thể này? IUC, sau đó ngoại lệ được ném chính xác một lần và quá trình này có thể sẽ bị gián đoạn sau đó (tất nhiên, sau khi hiển thị một cửa sổ bật lên đẹp cho người dùng). (còn tiếp tục ...)

2
Việc trả lại mã lỗi thay vì ném một ngoại lệ có thể gây khó khăn vì sau đó bạn phải tự mình truyền thông tin lỗi lên ngăn xếp cuộc gọi. Bạn nên sử dụng các ngoại lệ cho các lỗi tương đối hiếm có thể lan truyền trên một số khung ngăn xếp. Cả hai đều áp dụng ở đây.

1
Bạn đã bỏ lỡ điều gì đó: "khi cài đặt cấu hình ứng dụng bị thiếu hoặc chứa giá trị không hợp lệ", điều đó không giống như thông tin người dùng nhập sai. Đây là cấu hình cơ bản bị thiếu. Phải là một ngoại lệ tùy chỉnh và sẽ ngăn ứng dụng chạy.
jcollum

2
Trong ứng dụng cụ thể này, nó gần như hoàn toàn được điều khiển bởi các cài đặt trong tệp cấu hình. Nếu cài đặt không có trong đó (nơi chúng được mã hóa), ứng dụng không thể tiếp tục và phải chấm dứt. Một ngoại lệ hầu như được yêu cầu.
Mike Hofer

1
Điều này chắc chắn có thể đi vào ngữ nghĩa và cấu trúc mã của bạn rõ ràng sẽ chỉ định cách triển khai tốt nhất cho tình huống của bạn. Tuy nhiên, nếu bạn có quyền thống trị tự do trong thiết kế, tôi vẫn sẽ sử dụng một đối tượng để ghi lại lỗi và một lối thoát duyên dáng đối với một ngoại lệ, hiệu suất có phải là một vấn đề hay không.
Matt Jordan

-2

Bạn có thể thử kế thừa Ngoại lệ XML hoặc chỉ sử dụng nó.

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.