2013-08-16 23 views
7

ive chạy vào một vấn đề - đây là cấu trúc lớp học của tôiLàm thế nào để khởi tạo một giao diện mà có kiểu aguments của các loại khác Interface

public interface IModel{} 

public interface IGenericMapper<T> where T : IModel {...} 

public class ActualModel:IModel {...} 

public class ActualMapper: IGenericMapper<ActualModel> {...} 

mã thực tế của tôi để initialse mapper là:

IGenericMapper<IModel> mapper; 
mapper= new ActualMapper(); 

Nó không biên dịch. Tôi gặp lỗi

Không thể chuyển đổi hoàn toàn loại 'ActualMapper' sang 'IGenericMapper'. Một chuyển đổi rõ ràng tồn tại (là bạn thiếu một dàn diễn viên?)

Khi tôi đúc nó bằng cách sử

mapper= new ActualMapper() as IGenericMapper<IModel>; 

mapper không được khởi tạo đúng cách (nó trở lại như NULL)

Tôi đang thiếu gì - kể từ khi ActualMapper() thực hiện IGeneric Trình ánh xạ và loại impller của nó `IModel 'tại sao nó không thể khởi chạy trình ánh xạ.

Có cách nào khác để cấu trúc điều này để đạt được những gì tôi cần không?

Cảm ơn bạn rất nhiều

Lưu ý các giải pháp người đã đề xuất mang lại cho tôi lỗi biên dịch khác như giao diện bản đồ có các thành viên sau

T GetModel(busO bBusinessObject); 
busO SetBusObject(T source, busO target); 

rõ ràng bạn không thể có các loại generic như một tham số đầu vào khi của nó tuyên bố tại "out"

+4

bạn có thể thêm định nghĩa của ILFFMapper <> không? – LunicLynx

+0

'var ILFFMapper 'đó là một lỗi cú pháp, loại bỏ' var' từ khóa – Tommi

+0

Bạn cần một loại covarient. thử IGenericMapper < out T> –

Trả lời

4

bạn phải xác định

IGenericMapper<out T> 

để hỗ trợ kịch bản của bạn, nhưng điều này áp dụng các giới hạn khác.

Đơn giản chỉ cần IGenericMapper<IModel>! = IGenericMapper<ActualModel> ngay cả khi ActualModel : IModel

Trong hầu hết các tình huống nó làm cho tinh thần để có một giao diện cơ sở đó không phải là một generic. Xem ví dụ IList<T>, nó thực hiện IList.

Sau đó, bạn có thể chọn triển khai để triển khai rõ ràng các thành viên giao diện. Xem List<T>.GetEnumerator() : IEnumerable

Không sử dụng Generics theo giả định rằng bạn có thể loại bỏ việc truyền ở mọi nơi. Tôi đã thử nó C# chỉ đơn giản là không có các tính năng cần thiết cho việc này.

Tôi sẽ đề xuất giao diện IGenericMapper làm giao diện cơ sở cho IGenericMapper<T> sau đó thực hiện mã chung trên IGenericMapper và cuối cùng (và tại thời điểm đó bạn đã có loại) truyền trở lại loại cụ thể.

5

Chắc chắn bạn đang di chuyển vào lĩnh vực covarience ở đây với thay đổi Chung;

thử điều này:

public interface IModel{} 
public interface IGenericMapper< out T> where T : IModel{} 
public class ActualModel : IModel{} 
public class ActualMapper : IGenericMapper<ActualModel> {} 

và sau đó:

IGenericMapper<IModel> blah = new ActualMapper(); 

với hiện 'ra T' là tốt nhất bạn có thể làm là:

IGenericMapper<ActualModel> blah = new ActualMapper(); 

Đây là một hang thỏ , vì vậy hãy cẩn thận đặc biệt nếu bạn đã từng trộn hai số này :)

http://msdn.microsoft.com/en-us/library/ee207183.aspx

[Chỉnh sửa]

Nếu bạn muốn để có thể downCast các generic T, sau đó nó phải được out và bạn không thể sử dụng nó như một đầu vào. Tuy nhiên, bạn có thể di chuyển một số mục đó sang thời gian thực trong quá trình triển khai của bạn; tức là để kiểm tra xem bạn có thể truyền nó cho một kiểu máy hay không.

interface IGenericMapper<out TModel, in TKeyOrIdent> 

TModel GetModel(TKeyOrIdent bBusinessObject); 
void SetModel(object model, TKeyOrIdent target); 
Các vấn đề liên quan