Q: Protect readonly fields I have such piece of code:
namespace NetHacking
{
    interface IPlugin
    {
        void Execute(PluginData data);
    }

public class PluginData
{
    private readonly string ConstString = "Const data";

    public void Print()
    {
        Console.WriteLine(ConstString);
    }
}

[StructLayout(LayoutKind.Explicit)]
class ExternalPlugin : IPlugin
{
    internal class PluginHack
    {
        public string Text;
    }

    [FieldOffset(0)]
    private PluginData _original;
    [FieldOffset(0)]
    private PluginHack _hack;

    public void Execute(PluginData data)
    {
        _original = data;
        _hack.Text = "Hacking .NET";
    }
}

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()
    {
        return new ExternalPlugin();
    }
}}

In the example above PluginData data contains readonly string ConstString string. In theory PluginData passed to Execute method in IPlugin should be used to initialize plugin. Unfortunately ExternalPlugin can overriding ConstString externally.
Is there a way to protect against that ?

A: If you want to protect yourself against malicious plugins tampering with your application you should run them in their own AppDomain with limited permissions and communicate with the plugin via a well-defined interface. Do not give direct access to your program state to the plugin. Of course the plugin will still be able to modify its own copy of any data you send it, but your copy of the data will not be affected.

A: Mark's answer is proably the right one for your problem. I would like to add that beyond that, it is possible to check that the plugin assembly does not try to tamper before you load it.
To do that, You should require that it does not do unsafe code, does not call into any native function, does not do reflection, etc...
The  .net terrarium project uses checks like this. In this peer-to-peer application, user-provided .net code is passed around from one client to another. By applying a long, but finite list of checks, it is ensured that the code exchanged does not tamper the rules of the game and (more importantly) the computer running the game.  
