Невидимые входные параметры
Есть метод с параметрами по умолчанию. Требуется разделить способы вызова метода, а именно - если вызывается в родной сборке, возможность изменения параметров остается, если во внешней сборке, вызывается без изменения параметров по умолчанию.
Перегрузками невозможно, поясню:
static void Foo([CallerMemberName] string methodname = null)
{
Console.WriteLine(methodname);
}
Вызов метода:
Foo(); // вызов возможен в любой сборке
Foo("Bar"); // вызов возможен только в родной сборке
Иными словами нужен запрет на инициализацию параметров по умолчанию во внешней сборке, в идеале они должны быть просто невидимы.
Что не получилось: разные оболочки для метода, в этом cлучае methodname - имя оболочки, а не реально вызывающего метода. Что ожидаемо не получится - оценка изменений параметров по умолчанию, они изменяются всегда - либо задаются в вызове, либо изменяются вследствие атрибута. И отследить, кто их изменил и выбросить исключение вряд ли возможно.
Добавить in или out тоже вряд ли - параметр, скорее всего, может быть и в том, и в другом статусе.
Есть варианты, идеи?
Спасибо.
UPD1. Уточню проблему. Полный набор параметров выглядит примерно так:
static void Foo(string str1=null, string str2=null,[CallerMemberName] string methodname = null)
причем неатрибутированных параметров штуки 3, а то и 4. Поскольку они тоже дефолтные, то в итоге спиок вызова может включать от нуля до максимума параметров, и в этих условиях компилятор просто не соображает - то ли это str2, то ли methodname. Пока что это разрешается на уровне XML Comment'ов атрибутированных параметров - типа: "Don't change!", но кто их читает...
UPD2. @Alexander Petrov преложил обернуть атрибутированные параметры в классы. На самом деле эту возможность я обдумывал ранее, однако предположил, что в этой ситуации CallerMemberName будет обращаться к обертке. Но решил попробовать и, в принципе, получилось. Вызов сейчас выглядит примерно так:
Foo (new MemberName()); // или
Foo ("Bar", new MemberName())
Более того, для тех, кто не совсем в теме - таких аналогичных дефолтных атрибутов 4: CallerFilePath, CallerMemberName, int CallerLineNumber, и похожий на эти три string ParamName (префикс немного отличается). Обертка позволяет все 4 атрибутированных параметров упрятать в один Context(). Таким образом, ошибка связанная с путаницей параметров исключается - сложно представить, что кто-то захочет в качестве Str2 передать класс Context.
Однако возникла другая проблема. Параметр Context context - обязательный, т.е. всегда указывается в вызове. А поскольку его основная цель отработать по умолчанию, его указание в вызове излишне и желательно его избежать, пока же вот так:
// определение
static void Foo(MemberName membername, string str1=null, string str2=null)
=> Console.Writeline ($"{membername} {str1} {str2}");
// обертка
public class MemberName
{
public string ToString = null;
public MemberName([CallerMemberName] string memberName = null) => ToString = memberName;
}
// вызов
Foo (new MemberName());
// или
Foo ("Bar", new MemberName());
Спасибо всем, особенно @Alexander Petrov. Окончательный вариант будет оформлен в виде ответа.