(Образцы кода С# находятся в нижней части вопроса.)
У меня есть библиотека классов, разделяемая между несколькими решениями, с типом SharedType
. У меня есть метод в библиотеке классов, который обрабатывает коллекцию этого типа:
Sub ProcessSharedTypeEnumerable(src As IEnumerable(Of SharedType))
'do something here
End Sub
Каждое решение имеет свой собственный специфический тип, который должен отображать/преобразовывать в SharedType
:
Namespace Project1
Class ProjectType
End Class
End Namespace
Как я могу вызвать ProcessSharedTypeEnumerable
без необходимости конвертировать ProjectType
в SharedType
на сайт вызова?
Dim lst As New List(Of ProjectType)
'populate list
'instead of this:
ProcessSharedTypeEnumerable(lst.Select(Function(x) New SharedType With { 'populate members here' })
'use this:
ProcessSharedTypeEnumerable(lst)
Я знаю, что у меня может быть тип проекта, реализующий интерфейс из библиотеки классов, который имеет метод, который сопоставляется с общим типом
Public Interface ISharedTypeMappable
Function ToSharedType() As SharedType
End Interface
Тогда метод ProcessSharedTypeEnumerable
может принимать IEnumerable(Of ISharedTypeMappable)
и я могу вызвать .Select(Function(x) x.ToSharedType)
в ProcessSharedTypeEnumerable
чтобы получить IEnumerable(Of SharedType)
.
Есть ли более "правильный" способ сделать это? Общая ковариация и неявное преобразование? Некоторые встроенные механизмы преобразования.NET?
Примеры кода С#
Метод библиотеки классов:
static class Utils { //I know it an awful name ...
static void ProcessSharedTypeEnumerable(IEnumerable<SharedType> src) {
//do something here
}
}
Код проекта:
var lst = new List<ProjectType>();
//populate list
//instead of this:
Utils.ProcessSharedTypeEnumerable(lst.Select(x=>new SharedType { /* populate properties here */}));
//do this
Utils.ProcessSharedTypeEnumerable(lst);
Обновить
Я не хочу наследовать ProjectType
из SharedType
по двум причинам (1) ProjectType
уже наследуется от другого базового типа, и (2) SharedType
может иметь членов, которые не должны быть в ProjectType
.
EDIT: теперь это ответ сообщества wiki
В соответствии с просьбой, здесь была моя попытка реализовать Operator Widening CType
. Однако это не сработает. Может быть, кто-то, кто это читает, может это исправить.
Module Module1
Sub Main()
Dim lst As New List(Of ProjectType) From {
New ProjectType With {.t = "1"},
New ProjectType With {.t = "2"},
New ProjectType With {.t = "3"}
}
MsgBox(CType(lst(0), SharedType).s) 'This works'
ProcessSharedTypeEnumerable(lst) 'This does not :-( '
ProcessSharedTypeEnumerable(lst.Cast(Of SharedType).ToList) 'Neither does this :-( '
End Sub
Sub ProcessSharedTypeEnumerable(src As IEnumerable(Of SharedType))
For Each st As SharedType In src
MsgBox(st.s)
Next st
End Sub
Class SharedType
Property s As String
End Class
Class ProjectType
Property t As String
Public Shared Widening Operator CType(p As ProjectType) As SharedType
Return New SharedType With {.s = p.t}
End Operator
End Class
End Module
ProcessSharedTypeEnumerable
изменяет свойства любого из объектов ProjectType
в списке. Я думаю, что вам придется поставить в функции конвертера
Наследование?
Sub Main()
Dim lst As New List(Of ProjectType) From {
New ProjectType With {.s = "1"},
New ProjectType With {.s = "2"},
New ProjectType With {.s = "3"}
}
SharedType.ProcessSharedTypeEnumerable(lst)
End Sub
Shared Sub ProcessSharedTypeEnumerable(src As IEnumerable(Of SharedType))
For Each st As SharedType In src
MsgBox(st.s)
Next
End Sub
Class SharedType
Property s As String
End Class
Class ProjectType
Inherits SharedType
End Class
ProjectType
уже имеет другой базовый класс, чем SharedType
.
SharedType
. Таким образом, либоSharedType
должен быть классом, унаследованным отProjectType
либо это должен быть интерфейс, который реализован вProjectType
.ProjectType
может реализовать интерфейс, который имеет метод для сопоставления сSharedType
, аProcessSharedTypeEnumerable
может взятьIEnumerable
указанного интерфейса и использовать метод интерфейса для проецирования вIEnumerable(Of SharedType)
. Как я уже писал во втором разделе.