У меня была проблема желания, чтобы свойство имело внутренний метод считывания и защищенный метод set, как описано в этом вопросе, и я думал, что решил это путем выполнения следующего:
public class Accessor : AccessorBase
{
private Connection _connection;
protected void setConnection(Connection value)
{
_connection = value;
}
internal Connection GetConnection()
{
return _connection;
}
...
}
Однако я теперь получаю эту ошибку:
Непоследовательная доступность: тип параметра 'Соединение' менее доступен, чем метод 'setConnection (Соединение)'
Это вызвано тем, что я имею internal class Connection
. Я не сделал бы Connection
общедоступный класс, в то время как Accessor
потребности быть общедоступным, поэтому как я могу обойти эту ошибку, все еще поддерживая внутренний метод считывания и защищенный метод set?
... видны все защищенные члены... за пределами сборки и не может использовать внутренний тип.
Один из способов обойти это - сделать Соединение
публичным, сделав все его методы экземпляров и конструкторы внутренними.
Создайте публичный интерфейс IConnection
, который реализует Ваш внутренний объект Connection
. Ваши методы GetConnection
и SetConnection
принимают и возвращают IConnection
вместо Connection
.
Основные принципы СОЛИД снова выигрывают.
Coincoin is correct, Accessor
- это публичный класс, который любой может извлечь из него, это означает, что он также может быть получен из другой сборки. Этот производный класс теперь имеет защищенный метод, которому нужно передать внутренний (из другой сборки) класс. Это никогда не сработает.
Вам нужно либо сделать Accessor
внутренним или Connection
публичным, либо лучше следовать Randolphos answer
Вот пример кода проблемы
Assembly 1
//this class is only visible in Assembly 1
internal class Connection
{
}
public class Accessor
{
protected void SetConnection(Connection con) { }
}
Assembly 2 - имеет ссылку на Assembly 1
//possible because Accessor is public
DerivedAccessor : Accessor
{
void SomeMethod()
{
this.SetConnection(????) // you can't pass Connection, its not visible to Assembly2
}
}
Неочевидно, что ты не можешь этого сделать. Так как Подключение
является внутренним для какого-то класса, полученного от Accessor из другой сборки, Вы не сможете увидеть Подключение
, даже если Вы пометите сеттер как защищенный внутренний
, это ничего не решит.
Ваша единственная надежда - это сделать подключение класса публичным.
. Извините, если вам нужна эта точная настройка, вам нужно сделать ваш класс подключения
публичным.
К сожалению, C# не поддерживает модификаторы доступа "внутренний и защищён" (поддерживаются только "внутренний или защищён"), что означает, что любой член защищён
виден вне ассемблера и не может использовать внутренний тип.
Использование внутреннего
вместо защищенного
было бы наиболее логичным решением.
И вы могли бы проголосовать в Microsoft Connect, чтобы когда-нибудь он мог быть добавлен к C#.
Обновление: начиная с C# 7.2 вы можете использовать private protected
для этого.
Если класс Connection является внутренним, то вызывающий класс Accessor не сможет вызвать защищенное setConnection, так как у него нет доступа к Connection.
Если setConnection должен быть защищен, соединение должно быть публичным.