Đây là những gì tôi sẽ làm:
Giữ liên kết như một lớp trừu tượng, sử dụng một máy để nhanh chóng nó và vượt qua trong việc đóng cửa của bạn/phương pháp vô danh như một tham số cho phương pháp xây dựng của Nhà máy. Bằng cách này, bạn có thể giữ thiết kế ban đầu của mình với Liên kết dưới dạng lớp trừu tượng, buộc triển khai thông qua nhà máy và vẫn ẩn bất kỳ dấu vết cụ thể nào của Liên kết bên trong nhà máy.
Dưới đây là một số mã ví dụ:
class Program
{
static void Main(string[] args)
{
Link link = LinkFactory.GetLink("id",() =>
// This would be your onClick method.
{
// SetResponsePage(...);
Console.WriteLine("Clicked");
Console.ReadLine();
});
link.FireOnClick();
}
public static class LinkFactory
{
private class DerivedLink : Link
{
internal DerivedLink(String id, Action action)
{
this.ID = id;
this.OnClick = action;
}
}
public static Link GetLink(String id, Action onClick)
{
return new DerivedLink(id, onClick);
}
}
public abstract class Link
{
public void FireOnClick()
{
OnClick();
}
public String ID
{
get;
set;
}
public Action OnClick
{
get;
set;
}
}
}
EDIT: Trên thực tế, Đây có thể là một chút gần gũi hơn với những gì bạn muốn:
Link link = new Link.Builder
{
OnClick =() =>
{
// SetResponsePage(...);
},
OnFoo =() =>
{
// Foo!
}
}.Build("id");
Vẻ đẹp là nó sử dụng một khối init, cho phép bạn khai báo nhiều triển khai tùy chọn của các hành động trong lớp Liên kết như bạn muốn.
Đây là lớp Liên kết có liên quan (Với lớp bên trong Trình tạo kín).
public class Link
{
public sealed class Builder
{
public Action OnClick;
public Action OnFoo;
public Link Build(String ID)
{
Link link = new Link(ID);
link.OnClick = this.OnClick;
link.OnFoo = this.OnFoo;
return link;
}
}
public Action OnClick;
public Action OnFoo;
public String ID
{
get;
set;
}
private Link(String ID)
{
this.ID = ID;
}
}
Điều này gần với những gì bạn đang tìm kiếm, nhưng tôi nghĩ chúng tôi có thể tiến thêm một bước với các đối số được đặt tên tùy chọn, tính năng C# 4.0. Hãy xem tuyên bố ví dụ về Liên kết với các đối số được đặt tên tùy chọn:
Link link = Link.Builder.Build("id",
OnClick:() =>
{
// SetResponsePage(...);
Console.WriteLine("Click!");
},
OnFoo:() =>
{
Console.WriteLine("Foo!");
Console.ReadLine();
}
);
Tại sao điều này thú vị? Chúng ta hãy nhìn vào các lớp liên kết mới:
public class Link
{
public static class Builder
{
private static Action DefaultAction =() => Console.WriteLine("Action not set.");
public static Link Build(String ID, Action OnClick = null, Action OnFoo = null, Action OnBar = null)
{
return new Link(ID, OnClick == null ? DefaultAction : OnClick, OnFoo == null ? DefaultAction : OnFoo, OnBar == null ? DefaultAction : OnBar);
}
}
public Action OnClick;
public Action OnFoo;
public Action OnBar;
public String ID
{
get;
set;
}
private Link(String ID, Action Click, Action Foo, Action Bar)
{
this.ID = ID;
this.OnClick = Click;
this.OnFoo = Foo;
this.OnBar = Bar;
}
}
Bên trong lớp Builder tĩnh, có một phương pháp nhà máy xây dựng mà mất trong 1 thông số cần thiết (ID) và 3 thông số tùy chọn, OnClick, OnFoo và OnBar. Nếu chúng không được chỉ định, phương thức factory sẽ cho chúng thực hiện mặc định.
Vì vậy, trong các đối số tham số của hàm tạo cho Liên kết, bạn chỉ cần thực hiện các phương thức mà bạn cần, nếu không chúng sẽ sử dụng hành động mặc định, không thể là gì.
Hạn chế, tuy nhiên, là trong ví dụ cuối cùng, lớp Liên kết không trừu tượng. Nhưng nó không thể được khởi tạo bên ngoài phạm vi của lớp Link, bởi vì hàm tạo của nó là private (Bắt buộc sử dụng lớp Builder để khởi tạo liên kết).
Bạn cũng có thể di chuyển các tham số tùy chọn vào trong hàm tạo của Link trực tiếp, tránh sự cần thiết cho một nhà máy hoàn toàn.
Tôi không thấy lớp bên trong ẩn danh trong ví dụ bạn đã cung cấp. Nếu bạn muốn những người triển khai lớp trừu tượng của bạn luôn triển khai một số phương thức, bạn có thể tạo một phương thức trừu tượng trong lớp hoặc có nó thực hiện một giao diện. – tenor
@tenor, có một lớp vô danh nội tuyến được định nghĩa kế thừa từ 'Liên kết' và ghi đè phương thức' onClick'. Không giống như Java, C# không hỗ trợ các lớp ẩn danh để lấy được từ một kiểu người dùng đã cho. –
@ Dimitrov, cảm ơn vì đã chỉ ra điều đó. Tôi đang tìm kiếm một lớp "bên trong/lồng nhau" thực sự. Ví dụ được cung cấp trông giống như một lớp ẩn danh xuất phát từ một lớp hiện có, ít nhất là trong C# lingo. – tenor