Vì vậy, tôi có một hệ thống phân cấp đối tượng để tạo ra các điều khiển ui trong asp.net mvc và cố gắng đạt được một api thông thạo. Tôi làm một số lớp giả để tập trung vào vấn đề hiện tại.
Vì vậy, đây là "sai" codebase:Cách "ghi đè" các phương thức mở rộng trong .NET?
public abstract class HtmlElement { /* ... */ }
public abstract class UIElement : HtmlElement { /* ... */ }
public abstract class ButtonBase : UIElement { /* ... */ }
public class LinkButton : ButtonBase { /* ... */ }
public class ActionButton : ButtonBase { /* ... */ }
public static class HtmlElementExtensions
{
public static T Id<T>(this T item, string id) where T : HtmlElement
{
/* set the id */
return item;
}
}
public static class ButtonBaseExtensions
{
public static T Id<T>(this T item, string id) where T : ButtonBase
{
/* set the id and do some button specific stuff*/
return item;
}
}
Khi tôi cố gắng gọi Id trên LinkButton trình biên dịch nói rằng có cuộc gọi mơ hồ:
LinkButton lb = new LinkButton().Id("asd");
Tôi thực sự nghĩ rằng trình biên dịch chọn khớp gần nhất trong trường hợp này vì vậy nếu tôi có một lớp Script kế thừa từ HtmlElement hơn phương thức HtmlExtensions Id được gọi, và cho một LinkButton (vì các hạn chế), phương thức ButtonBase sẽ được gọi. Tôi có một giải pháp, nhưng tôi không chắc là có giải pháp nào tốt hơn.
tôi xóa phương pháp Id từ ButtonBaseExtensions và sửa đổi phương pháp Id HtmlElementExtensions như cách thức sau đây:
public static T Id<T>(this T item, string id) where T : HtmlElement
{
if (item is ButtonBase)
{
/* do some button specific stuff*/
}
/* set the id */
return item;
}
Bằng cách này mỗi hậu duệ lớp từ ButtonBase đang làm việc. Tôi không thực sự thích giải pháp của mình vì nó trộn lẫn logic HtmlElement với logic ButtonBase. Bất kỳ ý tưởng/đề xuất nào để có giải pháp tốt hơn? Tôi nghĩ tôi đặt chúng vào không gian tên khác nhau, nhưng chỉ trong một giây. Tôi cần phải sử dụng cả hai không gian tên, do đó, không giải quyết vấn đề.
Bạn có nghĩ rằng nó đáng nói đến trên diễn đàn msdn như một ý tưởng rằng trình biên dịch nên xem các hạn chế về các phương pháp mở rộng chung?
Trong khi chờ đợi tôi làm cho một số nghiên cứu thêm và bắt đầu một chủ đề trên các diễn đàn MSDN: link
Tôi đã thử một số methodds mở rộng không chung chung:
public class BaseClass { /*...*/ }
public class InheritedClass : BaseClass { /*...*/ }
public static class BaseClassExtensions
{
public static void SomeMethod(this BaseClass item, string someParameter)
{
Console.WriteLine(string.Format("BaseClassExtensions.SomeMethod called wtih parameter: {0}", someParameter));
}
}
public static class InheritedClassExtensions
{
public static void SomeMethod(this InheritedClass item, string someParameter)
{
Console.WriteLine(string.Format("InheritedClassExtensions.SomeMethod called wtih parameter: {0}", someParameter));
}
}
Và nếu tôi nhanh chóng sau đây:
BaseClass bc = new BaseClass();
InheritedClass ic = new InheritedClass();
BaseClass ic_as_bc = new InheritedClass();
bc.SomeMethod("bc");
ic.SomeMethod("ic");
ic_as_bc.SomeMethod("ic_as_bc");
Sản xuất sản lượng này:
BaseClassExtensions.SomeMethod called wtih parameter: bc
InheritedClassExtensions.SomeMethod called wtih parameter: ic
BaseClassExtensions.SomeMethod called wtih parameter: ic_as_bc
Cảm ơn,
Péter
Một phương pháp mở rộng là ** không ** một thay thế cho một phương pháp ảo, cũng có thể nó được thực hiện ảo. Đó là khá không rõ ràng lý do tại sao bạn cần một, cho rằng bạn tự khai báo các lớp học này. Chỉ cần thêm một phương thức ảo vào một trong các lớp cơ sở và ghi đè lên nó, khi cần thiết, trong một lớp dẫn xuất. –
Do api thông thạo, tôi phải sử dụng các phương pháp mở rộng. Các thừa kế generics chỉ làm việc với 2 mức độ thừa kế. Tôi đã viết một ví dụ với phương pháp mở rộng không thuộc về gen nơi trình biên dịch sử dụng hạn chế tham số để xác định đúng phương thức cần gọi. Tôi chỉ muốn trình biên dịch cũng đánh giá các hạn chế tham số chung. Tôi không thể viết "Id ButtonBase tĩnh công cộng (mục ButtonBase tĩnh này, id chuỗi)" thay vì "static T Id công cộng (mục T này, id chuỗi) trong đó T: ButtonBase" vì loại trả về sẽ là ButtonBase và ngắt chuỗi phương pháp của api thông thạo. –