ReadOnlyプロパティに属性が存在するかどうかをチェックする、次のようなカスタム ヘルパーを作成できます。
public static MvcHtmlString MyTextBoxFor<TModel, TValue>(
    this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)
{
    var metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
    // in .NET 4.5 you can use the new GetCustomAttribute<T>() method to check
    // for a single instance of the attribute, so this could be slightly
    // simplified to:
    // var attr = metaData.ContainerType.GetProperty(metaData.PropertyName)
    //                    .GetCustomAttribute<ReadOnly>();
    // if (attr != null)
    bool isReadOnly = metaData.ContainerType.GetProperty(metaData.PropertyName)
                              .GetCustomAttributes(typeof(ReadOnly), false)
                              .Any();
    if (isReadOnly)
        return helper.TextBoxFor(expression, new { @readonly = "readonly" });
    else
        return helper.TextBoxFor(expression);
}
属性は次のとおりです。
public class ReadOnly : Attribute
{
}
モデルの例:
public class TestModel
{
    [ReadOnly]
    public string PropX { get; set; }
    public string PropY { get; set; }
}
これが次の剃刀コードで機能することを確認しました。
@Html.MyTextBoxFor(m => m.PropX)
@Html.MyTextBoxFor(m => m.PropY)
次のようにレンダリングされます。
<input id="PropX" name="PropX" readonly="readonly" type="text" value="Propx" />
<input id="PropY" name="PropY" type="text" value="PropY" />
disabled代わりに必要な場合はreadonly、それに応じてヘルパーを簡単に変更できます。