Może nie takie prawdziwe, ale takie malutkie i niewinne 🙂 (a może nie takie niewinne?). Do napisania tego postu zainspirował mnie niedawno przeczytany inny post, pokazujący, jak można zmusić .NET do zrobienia czegoś co nie powinniśmy mieć możliwości zrobić. Jako, że mój post będzie związany z małą zagadką/konkursem na razie linka do inspiracji nie podam. Sposób jest w pełni legalny w .NET bo i program się kompiluje bez żadnych sztuczek. F5 i działa….

Zadanie

Zadanie będzie z typu akademickich, nie będzie pokazane tu jak zrobić coś potencjalnie niebezpiecznego, ale można od tego wyjść już do bardziej groźniejszych przypadków. Tak więc nakreślmy nasze zadanie. Mamy takowe klasy i kod:
PluginData.cs:

    public class PluginData
    {
        private readonly string ConstString = “Const data”;
        public void Print()
        {
            Console.WriteLine(ConstString);
        }
    }

IPlugin.cs:

    interface IPlugin
    {
        void Execute(PluginData data);
    }

No i nasz Program.cs:

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var data = new PluginData();
                var plugin = CreatePlugin();
                plugin.Execute(data);
                data.Print();
            }
            catch (Exception)
            {
                Console.WriteLine(“Error!”);             
            }
            Console.WriteLine(“End”);
            Console.Read();
        }
        private static IPlugin CreatePlugin()
        {
            //jakaś fabryka pluginów i akurat twój jest ładowany
            return new NaughtyPlugin();
        }
    }

Twój kawałek kodu to NaughtyPlugin i w założeniu powinien być ładowany z zewnętrznej biblioteki. Dla uproszczenia można mieć go w tym samym projekcie. Normalny wynik działania takiego kodu z pluginem powinien wyglądać mniej więcej tak:
normal_output
W zależności czy plugin wypisuje coś dodatkowego na konsoli i czy nie rzuca wyjątkiem. Czy da się tak go napisać, aby wynikiem było coś takiego:
output
I oczywiście program kończył swoje działanie? Tak więc oczywiste rozwiązania w którym plugin wypisuje i Hacking .NET i End odpadają ;). End jest wypisywane przez Program.cs.
Czyli opisując słowami czy da się zmienić łańcuch znaków ConstString w obiekcie PluginData? Jest readonly – raczej Reflection nic nie da, a może da? A może dynamic? A może się nie da i tylko to sobie wymyśliłem, że działa mi to w .NET 3.5/4.0 i VS 2008/2010 (choć środowisko nie ma tu znaczenia).
Niech to będzie konkurs – deadline do 29.10.2010 czyli od dzisiaj tydzień – ja mam jedno rozwiązanie (“niskopoziomowe” – niech to będzie jako podpowiedź), ale jak ktoś znajdzie inne działające to tym lepiej. Nagród wielkich nie przewiduje – w zasadzie żadne Chwała i sława. Może jednak znajdę jakąś koszulkę dla zwycięzcy. Oczywiście swoje rozwiązanie także opublikuję. Odpowiedzi w komentarzu są moderowane, więc nie będę ich publikował przed końcem albo na maila (jest w profilu).