C#には「リフレクション」という便利な機能があります。
これは、メソッドなどを動的に呼び出したり、インスタンスを動的に生成したりすることができる機能です。

ただ、この機能、実はprivateに設定したメンバも呼び出してしまうことができます。
つまり、他から呼び出されると困るからprivateにしたメソッドがあったとしたら、それを利用者が意図的に呼び出すことが出来てしまう、という訳です。
まあ、利用者がprivateメンバまでクラス構造を理解していないとできませんが。
注意:フィールドおよび構造体の引数なしコンストラクタに対するアクセスを検出する方法はありません。

一般的なリフレクションの使い方は以下の通りです。

//using System.Reflection;
typeof(Program).InvokeMember("Test", BindingFlags.Static | BindingFlags.NonPublic| BindingFlags.InvokeMethod, null, null, new object[0]);


Programというクラスの静的privateメソッド「Test()」を呼び出す例です。
この呼び出しはProgramクラス以外や、他のアセンブリからも呼び出すことができてしまいます。

そこで、このような呼び出しが行われた時に検出するプログラムを作りましたので、以下に提示します。

    //各自で名前空間を定義してください。
    using System;

    /// <summary>
    /// 現在の操作がリフレクションで呼び出されているかどうか調べる機能を提供します。
    /// </summary>
    public static class ReflectionChecker
    {
        /// <summary>
        /// 指定した階層のメンバがリフレクションによって呼び出されたかどうかを取得します。
        /// </summary>
        /// <param name="count">調べるメソッドの呼び出し階層</param>
        /// <returns>対象のメンバがリフレクションで呼び出されている場合はtrue</returns>
        /// <remarks>
        /// 呼び出し階層は、0以上の整数を指定します。
        /// 例えば、このメソッドを呼び出したメンバを指定するには0、その直前のメンバは1となります。
        /// </remarks>
        public static bool IsReflected(int count = 0)
        {
            var trace = Environment.StackTrace.Split('\n');
            if (trace.Length >= 5 + count)
            {
                var current = trace[4 + count];
                if (current.Contains("System.RuntimeMethodHandle.InvokeMethod("))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// 指定した階層以下のいずれかのメンバがリフレクションによって呼び出されたかどうかを取得します。
        /// </summary>
        /// <param name="count">調べるメソッドの呼び出し階層</param>
        /// <returns>対象のメンバ以下がリフレクションで呼び出されている場合はtrue</returns>
        /// <remarks>
        /// 呼び出し階層は、0以上の整数を指定します。
        /// 例えば、このメソッドを呼び出したメンバを指定するには0、その直前のメンバは1となります。
        /// </remarks>
        public static bool IsReflectedAny(int count = 0)
        {
            var trace = Environment.StackTrace.Split('\n');
            if (trace.Length >= 5 + count)
            {
                for (int i = 4 + count; i < trace.Length; i++)
                {
                    var current = trace[4 + count];
                    if (current.Contains("System.RuntimeMethodHandle.InvokeMethod("))
                        return true;
                }
            }
            return false;
        }

このメソッドの利用方法は以下の通りです。

        private static void Test()
        {
            if (ReflectionChecker.IsReflected())
                throw new UnauthorizedAccessException();
        }


このようなコードをメソッド内先頭に追加することで、リフレクションを使ってこのメソッドを呼び出したとき例外が発生します。

ちなみに、この方法はプロパティやコンストラクタでも使えます。
どうしてもリフレクションで呼び出されたら困るメンバを定義する時に役立ててください。
最後に、もしpublicやprotectedメンバでこれを使う場合は、ちゃんとコメントに「このメンバをリフレクションで呼び出すことはできません。」と書いておくことをお勧めします。